- Home /
How to convert game object world position to hex grid cell coordinates?
So basically what i want to do is simple, i have a hex grid and a game object let's say it's the player, what i want to do is know on wich cell the player is on based on his world position, this would be easy on a simple grid but on a hex grid its giving me a headach, if anyone can give me an approache to this it would be very much appreciated thank you.
Answer by Cherno · Apr 14, 2018 at 09:08 PM
public Vector2 GetHex(Vector3 point)
{
int column;
int row;
// Find out which major row and column we are on:
row = (int)(point.z / 0.87f);
column = (int)(point.x / (radius + radius/2));
// Compute the offset into these row and column:
float dz = point.z - (float)row * 0.87f;
float dx = point.x - (float)column * (radius + radius/2);
// Are we on the left of the hexagon edge, or on the right?
if (((row ^ column) & 1) == 0) {
dz = 0.87f - dz;
}
int right = dz * (radius - radius/2) < 0.87f * (dx - radius/2) ? 1 : 0;
// Now we have all the information we need, just fine-tune row and column.
row += (column ^ row ^ right) & 1;
column += right;
return new Vector2(Mathf.RoundToInt(column), Mathf.RoundToInt(row / 2));
}
It shows some good results but i run to some issues that i'm trying to fix, what's the 0.87 for? and the radius is it the inner radius of the hex or the outer?
The 0.87 is an approximation of $$anonymous$$athf.Sin($$anonymous$$athf.PI / 6f)
or $$anonymous$$athf.Sqrt(3) / 2f
which is simply the value of "sin(60°)". A more exact value is "0.866025403784438646". Though it's easier to define it as static float variable. See my comment below.
The radius is the outer radius or the edge length of one of your hexagon cells. $$anonymous$$eep in $$anonymous$$d that a hexagon is made up of 6 equilateral triangles. So an outer edge has the same length as the outer radius (the distance from center to any corner). Also all angles in one of those triangles are 60°. This can be proven by 360°/6 == 60° or since an equilateral triangle has 3 identical angles and a triangle has 180°--> 180°/3 == 60°
I've once posted an image over here that might come in handy
Note there's a small error in your implemenation. You don't take the radius into account when calculating the y (row) position. You have to divide by the (radius*sin(60°)), not just by the sin.
Also i would strongly recommend to use a static float constant for sin(60).
There are some simplifications you can do as well:
radius - radius/2
is justradius/2
orradius*0.5f
The two explicit float casts are unnecessary since the second operand is a float, so the result will be a float as well.
As mentioned above replace all 0.87f with a proper calculated constant.
The two RountToInt at the end is completely unnecessary since row and column are already integers. The divide by 2 is already an integer divide ("row" as well as "2" are integers) so the result will be an integer as well.
You may want to use Vector2Int as return type if you use the latest Unity version.
Since it's a pure 2d problem i would recommend to pass in a Vector2 ins$$anonymous$$d of Vector3. If you actually work in 3d you would have to convert the coordinates.
Finally be aware that this calculation does only work for positive values. It does not proper transition into the negative values.
I've made a "fixed" version ^^:
static float sin60 = $$anonymous$$athf.Sqrt(3f) * 0.5f;
public static Vector2 GetHex(Vector2 point, float radius)
{
// Find out which major row and column we are on:
int row = (int)(point.y / (radius * sin60));
int column= (int)(point.x / (radius * 1.5f));
// Compute the offset into these row and column:
float dy = point.y - row * radius * sin60;
float dx = point.x - column * radius * 1.5f;
// Are we on the left of the hexagon edge, or on the right?
if (((row ^ column) & 1) == 0)
{
dy = sin60 - dy;
}
int right = dy * radius * 0.5f < sin60 * (dx - radius * 0.5f) ? 1 : 0;
// Now we have all the information we need, just fine-tune row and column.
row += (column ^ row ^ right) & 1;
column += right;
return new Vector2(column, row / 2);
}
Your answer
![](https://koobas.hobune.stream/wayback/20220612160746im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
How to increment value of axis when something happens 2 Answers
Why Do My Obstacles Do This In My Object Pooler? 1 Answer
I need help with a Text Location script (Ho bisogno di aiuto con uno script di posizione del testo) 0 Answers
How can i place subjects in different positions? 0 Answers
Making a gameobject move to a position 2 Answers