I recently started working on a project with a friend that involves a hex map.
There is an amazing guide here I couldn’t possibly top. I’m going to cover a few items that were absent I needed. I used an axial coordinate system. I haven’t seen a better method.
This post will cover:
- Calculating Unity world coordinates from array coords, where to instantiate
- Trimming for a hexagonal shaped map
- Marking a border
- Finding neighboring hexagons within a radius
Instantiating hex pieces, calculating Unity world coordinates from array coords.
I stored my hexagons in a 2d array let’s say HexMap[,]. The picture to the left shows an example. Please note on an axial system (aka slanted) the Z axis is slanted and the Y axis is vertical. To find where to place hexagons at their correct ‘world coordinate:”
Create a variable that stores the hex models radius (it’s side length in Unity)
Next calculate the apothem which is :
Mathf.Sqrt(Mathf.Pow(radius, 2) – Mathf.Pow((radius / 2), 2));
Once you have the apothem you can easily calculate the world coordinates for any Hex based on the following :
x world coordinate = (x Array Coordinate * (1.5 * radius))
z world coordinate = ((z Array Coordinate * (2 * apothem)) + (x Array Coordinate * apothem))
Trimming the edges to create a Hex shaped map
To accomplish this look the array (map) needs to be an odd number of hexes and square, the example above is 5×5. To locate of the unwanted Hexagons marked in yellow above, red to the right.
amountToTrim = xMax / 2; (floor division)
mapSize = (xSize-1)*2
Every tile that meets the following conditions needs trimmed:
if (x+z < hexAmountToTrim || x+z > (mapSize – hexAmountToTrim ) ) {}
Marking a Border
I marked the border for two reasons. I felt it would look nicer to add a trim piece to the map and my path finding algorithm does not check if coordinates are valid. To handle this I flag border pieces as invalid/non-traversable so if/when they are reached they are ignored.
When generating the map catch the pieces and flag as a border only if they are not caught while trimming the edges above. This will only catch a 1 hex deep border. If you want more you’ll need to check for different conditions.
(x + z < hexAmountToTrim + 1 || (x + z > ((mapSize – 1) * 2) – (hexAmountToTrim + 1)) || z == 0 || x == 0 || z == mapSize – 1 || x == mapSize – 1)
Finding a hexgons neighbor’s
The example code will find the coords within a perimeter of three around the hexagon at the coordinates of 27,24.
1 int perimeter = 3;
2 int startingX = 27;
3 int startingZ = 24;
4 int areaToCutAround = startingX+startingZ;
5 for (int x = startingX - perimeter; x <= startingX + perimeter; x++)
6 {
7 for (int z = startingZ + perimeter; z >= startingZ - perimeter; z--)
8 {
9 if ((x + z < areaToCutAround - perimeter) || (x + z > (areaToCutAround + perimeter)))
10 {
11 //area being trimmed
12 }
13 else { //mark this x,z its within the perimeter }
14 }
15 }