Which way is considered more efficient to compare these variables?

Viewed 62

I am writing a player controller and I am getting the player movement on two axes (X, Y). The values can roughly be -1, 0, 1 on each axis. Positive values point UP and to the RIGHT. It is impossible for both values to be zero based on a previous check I make.

Based on their combination I want to determine the direction the player is facing. There are eight possible directions for the player to take. I use the enum: FacingDirection, to pass the direction.

Example to clarify:
If X = 1 and Y = 0 then the player is moving towards the RIGHT side of the screen.

If X = -1 and Y = -1 then the player is moving towards DOWN LEFT corner of the screen.

I have come up with two possible solutions to this problem, but I wish to know which one is more efficient.
Both solutions use _inputs, which is a 2D vector, to get the values for X and Y.

Solution A

private FacingDirection findMoveDirection() {
    int x = 0, y = 0;

    float testing = _inputs.x;
    for(int i = 0; i < 2; i++) {
        int temp;
        if (testing != 0) {
            temp = (testing > 0) ? 1 : -1;
        } else {
            temp = 0;
        }

        if (i < 1) {
            x = temp;
        } else {
            y = temp;
            break;
        }
        testing = _inputs.y;
    }

    int check = x + y;
    switch (check) {
        case 2 : {
            return FacingDirection.UP_RIGHT;
        }
        case -2 : {
            return FacingDirection.DOWN_LEFT;
        }
        case 1 : {
            if (x > 0) {
                return FacingDirection.RIGHT;
            } else {
                return FacingDirection.UP;
            }
        }
        case 0 : {
            if (x > 0) {
                return FacingDirection.DOWN_RIGHT;
            } else {
                return FacingDirection.UP_LEFT;
            }
        }
        case -1 : {
            if (x < 0) {
                return FacingDirection.LEFT;
            } else {
                return FacingDirection.DOWN;
            }
        }
        default : {
            Debug.LogWarning("Something went wrong while determining moving direction. Returning DOWN as moving direction.");
            return FacingDirection.DOWN;
        }
    }

Solution B

This is a more straight-forward if/else approach.

private FacingDirection findMoveDirection() {
    float x = _inputs.x, y = _inputs.y;

    if (x != 0) {
        if (x > 0) {
            if (y != 0) {
                if (y > 0) {
                    return FacingDirection.UP_RIGHT;
                } else {
                    return FacingDirection.DOWN_RIGHT;
                }
            } else {
                return FacingDirection.RIGHT;
            }
        } else {
            if (y != 0) {
                if (y > 0) {
                    return FacingDirection.UP_LEFT;
                } else {
                    return FacingDirection.DOWN_LEFT;
                }
            } else {
                return FacingDirection.LEFT;
            }
        }
    } else {
        if (y > 0) {
            return FacingDirection.UP;
        } else {
            return FacingDirection.DOWN;
        }
    }
}
2 Answers

You could combine both values into a single one. For instance:

int directions = y * 2 + x;

It uniquely identifies a direction.
Its allowed values are: -3 ... +3, excluding 0.
Then you can use it in a switch (Solution A without ifs) or as a dictionary key.

Solution B is definitely faster, it does 4 comparisons in the worst case, while solution A does 8 comparisons, also in the worst case, just within the for loop.

You can benchmark both methods and verify that. It's always a good idea to actually measure the performance: this code is quite simple but in more complex situations there are factors that are not obvious (ie. CPU caching effect when dealing with many objects in memory).

Related