Hi, I’m doing a Hex game right now…I already have the Hex grid, I store all of my hexagons in a Hash Table but now I have no clue how to find the neighbors of every Hexagon…Can anyone help me? That’s the script I use to create my Hex grid and that’s how it looks…The Hexagon that it’s on red is the (0, 0)…Please, I have been stuck on this for 3-4 days.
Use a 2D array or list instead of a Hashmap, then you can easily find neighbours.
Alternatively, have each hex store its neighbours.
Everything you need is here:
I use the cube method, so I can grab neighbors based on direction hex.getNeighbor(int d) direction being clockwise from 0-5 (zero being up).
Oh ok…One question, why a List instead of a Hashmap?
Thanks, going to check it right now.
What i did when i had to make a grid system that allowed for odd shaped grids with lots of gaps etc was make my own struct to represent position on the grid. It did all the maths for working out positions behind the scene. Then i used it for the key in a dictionary holding the grid pieces.
Copy pasting some code over from an older one i made a struct that handles hexagonal grid positions, including working out all its neighbour positions.
It uses integers internally to mark its position in the grid then uses a grid size that you set at the top to calculate actual world position. It can work out its neighbouring positions just by incrementing/decrementing its x/y integers. And i’ve implemented the implicit conversions so you use it pretty interchangeably with vector3 positions.
Disclaimer: I did this very roughly in about 20 minutes and all aspects of it are not fully tested.
using System;
using System.Collections.Generic;
using UnityEngine;
internal struct HexPosition
{
const float HexSpacing = 1.5f;
private int grid_x;
private int grid_y;
internal float pos_x
{
get
{
if (grid_y % 2 == 0) // We're on an even row.
{
return grid_x * HexSpacing;
}
else // We're on an odd row.
{
return (grid_x * HexSpacing) + (HexSpacing * 0.5f);
}
}
}
internal float pos_y
{
get
{
return grid_y * (HexSpacing * 0.5f);
}
}
internal Vector3 Vector3
{
get
{
return new Vector3(pos_x, pos_y, 0f);
}
}
internal HexPosition(Vector3 WorldPosition)
{
grid_y = Mathf.RoundToInt(WorldPosition.y / (HexSpacing * 0.5f));
if (grid_y % 2 == 0) // We're on an even row.
{
grid_x = Mathf.RoundToInt(WorldPosition.x / HexSpacing);
}
else // We're on an odd row.
{
grid_x = Mathf.RoundToInt((WorldPosition.x - (HexSpacing / 2)) / HexSpacing);
}
}
internal HexPosition(int grid_x, int grid_y)
{
this.grid_x = grid_x;
this.grid_y = grid_y;
}
internal List<HexPosition> NeighbourPositions
{
get
{
List<HexPosition> List = new List<HexPosition>();
int xOffset = 0;
if (grid_y % 2 != 0)
xOffset = 1;
// On the same row.
List.Add(new HexPosition(grid_x - 1, grid_y));
List.Add(new HexPosition(grid_x + 1, grid_y));
// 2 in row above
List.Add(new HexPosition(grid_x + xOffset - 1, grid_y + 1));
List.Add(new HexPosition(grid_x + xOffset, grid_y + 1));
// 2 in row below
List.Add(new HexPosition(grid_x + xOffset - 1, grid_y - 1));
List.Add(new HexPosition(grid_x + xOffset, grid_y - 1));
return List;
}
}
internal HexPosition NeighbourInDirection(int Direction)
{
Direction = Mathf.Clamp(Direction, 0, 5);
int xOffset = 0;
if (grid_y % 2 != 0)
xOffset = 1;
switch (Direction)
{
case 0:
return new HexPosition(grid_x - 1, grid_y);
case 1:
return new HexPosition(grid_x + xOffset - 1, grid_y + 1);
case 2:
return new HexPosition(grid_x + xOffset, grid_y + 1);
case 3:
return new HexPosition(grid_x + 1, grid_y);
case 4:
return new HexPosition(grid_x + xOffset, grid_y - 1);
case 5:
return new HexPosition(grid_x + xOffset - 1, grid_y - 1);
}
throw new Exception("Shouldn't actually be possible to reach here unless i stuffed up");
}
public static bool operator ==(HexPosition A, HexPosition B)
{
if (A.grid_x != B.grid_x)
return false;
if (A.grid_y != B.grid_y)
return false;
return true;
}
public static bool operator !=(HexPosition A, HexPosition B)
{
if (A == B)
return false;
return true;
}
public static bool operator ==(HexPosition A, Vector3 B)
{
HexPosition Comparison = new HexPosition(B);
if (A == B)
return true;
return false;
}
public static bool operator !=(HexPosition A, Vector3 B)
{
HexPosition Comparison = new HexPosition(B);
if (A == B)
return false;
return true;
}
public static implicit operator HexPosition(Vector3 Position)
{
return new HexPosition(Position);
}
public static implicit operator Vector3(HexPosition Position)
{
return Position.Vector3;
}
public static bool Compare(Vector3 A, Vector3 B)
{
return (new HexPosition(A) == new HexPosition(B));
}
public override string ToString()
{
return "X" + grid_x + "Y" + grid_y;
}
}
Very rough script just to show using it to create a hex based grid, finding an object in the grid and finding its neighbours.
using System;
using System;
using System.Collections.Generic;
using UnityEngine;
internal class HexWorld : MonoBehaviour
{
Dictionary<HexPosition, GameObject> HexGrid = new Dictionary<HexPosition, GameObject>();
void Start()
{
// Create the grid
for (int x = 0; x < 10; x++)
for (int y = 0; y < 10; y++)
{
HexPosition NewPos = new HexPosition(x, y);
GameObject NewObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
NewObject.transform.position = NewPos.Vector3;
HexGrid.Add(NewPos, NewObject);
}
// Find an object in the grid.
HexPosition SelectedPosition = new Vector3(4f, 4f);
GameObject SelectedObject;
HexGrid.TryGetValue(SelectedPosition, out SelectedObject);
if (SelectedObject != null)
{
// Highlight selected object
SelectedObject.GetComponent<MeshRenderer>().material.color = Color.red;
// Find its neighbours
List<HexPosition> Neighbours = SelectedPosition.NeighbourPositions;
foreach(HexPosition NeighbourPosition in Neighbours)
{
GameObject NeighbourObject;
HexGrid.TryGetValue(NeighbourPosition, out NeighbourObject);
if (NeighbourObject != null) // Highlight the neighbours
NeighbourObject.GetComponent<MeshRenderer>().material.color = Color.blue;
}
}
}
}
This is exactly the same approach i used, with the minor difference of using the cube model. A struct with x,y,z and a dictionary. For game play, my hex class stores its neighbors as well. A little more overhead, but a speed improvement for pathing and such, over constantly using the dictionary for lookups.
What I love about that post at redblob, is that is pretty much a complete source. Virtually everything you ever need to know about hex maps is covered.
I bookmarked it for later reading. Looked really good.
I know this isn’t a specific answer to your question but this is a tutorial that Quill18 does a very good job explaining and goes into a lot of detail on. If you go through this and the tutorial zombiegorilla posted and the one I’ve posted below you should have a proper understanding on how to do everything and thanks for the link myself mod, I’ve been wondering about hexagon maps myself.
