Hex ShootAction Range

After implementing the hex grid, I was double checking some differences and ran into a bug. I changes the maxShootDistance = 2 and then went to a spot on the grid to check the range. The max range doesn’t seem to cover all hexes within 2 units. I know it’s got to be that ShootAction is using the (square) grid coordinate system, but I’m having no luck converting this to hexes.

1 Like

This is something I’ve encountered in previous iterations of my own hex based solutions… The problem is that simple math doesn’t work… Ordinarily, I just use the Pathfinding system to derive the distance (by measuring the path), but this isn’t the best solution (and in fact, in order to make this not insanely cumbersome, you would only want to test cells that on a square grid were less than distance + 1 away).

We need to do a wee bit more math to get the actual distance between two cells…
There are a lot of complicated formulas for determining the distance between the centers of two given hex cells, but since we’re using GridPositions, we get to normalize the distance between any two adjacent tiles to 1…
Knowing this, then we can we should be able to calculate the distance between any 2 given tiles with this formula:
image
Note that the latter half of the formula x1 is >= x0 and y1 >=y0 (it doesn’t matter where we square them).
So here’s what I’ve come up with, converting things to X,Z

public static int HexGridDistance(GridPosition a, GridPosition b)
{
    int deltaX = Mathf.Abs(a.x-b.x);
    int deltaZ = Mathf.Abs(a.z-b.z);
    int xSquared = deltaX * deltaX;
    int zSquared = deltaZ * deltaZ;
    int crossMultiple = deltaX * deltaZ;
    return Mathf.FloorToInt(Mathf.Sqrt(xSquared + zSquared + crossMultiple));
}

An alternate take on this would be to make it a function within GridPosition itself

public int HexGridDistance(GridPosition other)
{
     int deltaX = Mathf.Abs(x-other.x);
    int deltaZ = Mathf.Abs(z-other.z);
    int xSquared = deltaX * deltaX;
    int zSquared = deltaZ * deltaZ;
    int crossMultiple = deltaX * deltaZ;
    return Mathf.FloorToInt(Mathf.Sqrt(xSquared + zSquared + crossMultiple));
}
2 Likes

Thanks for the above. You got me 98% of where I needed to be. Implementing the above, I was getting some hexes that were really a range of 3 treated as 2/valid. I found a reference via Google about even/odd row offsets and wondered if that would make a difference, so I added the following check to z values and now get what’s expected!

Image4

While I had been working with the range in ShootAction, I overlooked that GridSystemVisual.ShowGridPositionRange was also calculating the range independently.

Now that everything is getting the range from the same method, things are looking great!

2 Likes

Would it be possible for you to send a snippet of your ShowGridPositionRange checks? I’ve tried implementing the above math, and as far as I can tell that seems to work. But I’m still getting weird issues, even when HexGridDistance is the only check I have.

Edit: I tossed this into the GridTesting script to double-check distances, and the results are all over the place. Sometimes adjacent tiles have a distance of 2, other positions two tiles away have a distance of 1.

if (Input.GetKeyDown(KeyCode.T)) {
            GridPosition unitGridPosition = UnitActionSystem.Instance.GetSelectedUnit().GetGridPosition();
            GridPosition mouseGridPosition = LevelGrid.Instance.GetGridPosition(MouseWorld.GetPosition());
            Debug.Log(LevelGrid.HexGridDistance(unitGridPosition, mouseGridPosition));
        }

I went back and paid closer attention (I should have used more contrasting colors) and noticed the same inconsistency. I remember Code Monkey doing some specific calculations based on even/odd rows and that got me searching that led me to Hexagon-Grid Distance - Unity Answers

The below is the rough conversion to HexGridDistance but it seems to be giving more consistent correct ranges for me.

Tomorrow when I’m more awake I’m going to look closer at the math and see if I can make any sense out of it - I messed up trying to change Y references to Z so I’m leaving it until I’m clear-headed.

2 Likes

I can’t say I understand the math myself, but I’ve been testing all potential edgecases for the last hour or so, and I’ve yet to get a wrong result. Thank you very much for the help!

1 Like

Privacy & Terms