Search code examples
c#opengltry-catchgame-engineopentk

How can I avoid poor program performance from a TRY statement?


I am currently developing a basic voxel (cuboid) game engine, and I have encountered a performance issue. Every frame the game:

Finds player's viewing direction → Checks every co-ordinate in the player's direct view path → Finds closest occupied space → Draws a wireframe around this block.

I am using OpenTK, a binding of OpenGL for .NET/Mono (specifically C#). My code OnRenderFrame contains this:

try
{
    for (int i = 0; i < 8; i++)
    {
        Vector3 block = InterfaceUtils.FindBlockLoc(Utilities.RoundToInt(cam.Position + (cam.lookat * i)));
        if (block != Vector3.Zero)
        {
            // Draw the wireframe
        }
    }
}
catch
{
}

The purpose of this code is to check up to eight blocks from the player until it finds a block. The only problem with this is that the try statement most often throws a (handled) exception: but the lag caused by this is massive. When I look into space, I only get 11FPS, but I get 50 if the code is successful.

If the code is successful (it can draw the wireframe), I get this:

The block-finding works by checking the objects list for a block in that location.

public static Vector3 FindBlockLoc(Vector3 location)
{
    Vector3 result = new Vector3(Vector3.Zero);

    result = Deltashot.Game.objects.Find(v => v.Position == location).Position;
    if (result != null)
    {
        return result;
    }
    else
    {
        return Vector3.Zero;
    }
}

However, this returns a NullReferenceException and I'm forced to use a TRY statement to get it to run. Which is back to square one again...


Solution

  • Throwing and catching Exceptions is a costly operation in C#, and it seems you are using exceptions as flow control.

    Your should avoid the NullReferenceException instead of catching it whenever it happens.

    I would guess the exception happens here:

    result = Deltashot.Game.objects.Find(v => v.Position == location).Position;
    

    I'd suggest something like this:

    public static Vector3 FindBlockLoc(Vector3 location)
    {
        var result = Deltashot.Game.objects.Find(v => v.Position == location);
    
        if (result != null && result.Position != null)
        {
            return result.Position;
        }
        else
        {
            return Vector3.Zero;
        }
    }