Custom class implementation of AStar2D for hexagonal grids in the Godot game engine. Minimum setup and supports both horizontal and vertical offset, different tilemap layers and setting specific tiles as obstacles/solid points.
The way that 2D grids count coordinates for hexagonal grids causes some issues because hexagonal grids have 6 neighbors instead of 4, which means that if you connect the points that a normal grid needs you'd have 2 disconnected points left. But at the same time if you enable all 4 diagonals you'll get 2 extra points that break the pattern.
The 2 disconnected points that need to be connected to the center hexagonal cell switch directions every row (or column for vertical offset). For even row numbers the 2 missing points are top-left and bottom-left, but for odd row numbers it's top-right and bottom-right. For vertical offset grids it's swapped around, for even column numbers the missing points are top-left and top-right, but for odd it's bottom-left and bottom-right.
I have basically added a function that connects a point to its neighboring 6 points using the logic above that's called for each (non-solid) point.
- Download the class .gd file and place anywhere inside your Godot project.
- Instance the class in a script where you have a reference to your TileMap.
@onready var tile_map: TileMap = $TileMap
var tile_layer: int = 0
var astar_hex: AStarHexGrid2D
func _ready():
astar_hex = AStarHexGrid2D.new()
- Call the
setup_hex_grid()
function passing the TileMap and layer as a parameters.
astar_hex.setup_hex_grid(tile_map, tile_layer)
- Your grid is set up now, to get the path from one point to another you'll need to get the map coordinates of the points using the function built into TileMap
tile_map.local_to_map(point)
.
var from_point = tile_map.local_to_map(player.position)
var to_point = tile_map.local_to_map(get_global_mouse_position())
- Then you just call the function
get_path()
passing in the map coordinates of thefrom
andto
points which returns a PackedVector2Array containing the path fromfrom_point
toto_point
in game (not map) coordinates.
var path = astar_hex.get_path(from_point, to_point)
To set a specific tile in the tile set as solid/obstacle (i.e. the pathfinder can't navigate through it) you need to add a custom data layer bool named "solid" in the tile set and enable it for the solid tiles in the tile set.
An array containing all the points in the pathfinding grid stored as Vector2's of the map coordinates where the index is the point id in the grid.
The TileMap assigned for the pathfinding grid.
Assigns tile_map
to the passed_tile_map
and loops over all the used cells in the passed layer in the tile map adding them to the pathfinding grid (if they are not solid) using add_hex_point()
and connecting it to its neighbors using connect_hex_point()
.
Adds the passed cell to the pathfinding grid and appends it to points_arr
.
Connects all 6 neighboring cells to the passed center cell in map coordinates in the pathfinding grid to enable pathfinding between them freely. It uses a simple even/odd logic to decide whether to add the top-left and bottom-left cells or the top-right and bottom-right cells respectively (for horizontal offset, vertical offset uses top-right and top_left vs bottom_right and bottom_left). This function is called automatically in the class for every non-solid point.
Returns the point id (also the index in points_arr
) of the cell with the given map coordinates.
Returns the pathfound path from from_point
to to_point
as a PackedVector2Array of game (not map) coordinates where the first element is the first step and the last element is the target at to_point
(automatically gets the id's for the points).