A comprehensive implementation of 3D hexagonal maps in Godot 4, featuring terrain rendering, heightmap loading, entity placement, camera controls, rivers, and territory borders.
Based on the Nyika project implementation with influences from Red Blob Games and Catlike Coding.
- Pointy-top hexagons with odd-row offset coordinates
- Discrete elevation tiers for clean "board game" aesthetic (Civ 6 style)
- 3D hex prism mesh generation with dual materials (top surface + cliff sides)
- Heightmap loading with auto-discovery from assets folder
- Smooth ribbon river meshes with animated water shaders
- Territory border rendering (Civ-style faction borders)
- Orthographic camera with zoom and pan controls
- Mini-map with click-to-pan navigation
- External asset integration (Meshy AI GLB models)
- Open the project in Godot 4.x
- Place heightmap images (
.jpgor.png) inassets/maps/ - Run the main scene
See hex-map-guide.md for comprehensive technical documentation covering:
- Hex coordinate system and math
- Terrain rendering with elevation tiers
- Heightmap loading and terrain generation
- Entity placement with AABB-based Y-offset
- Camera system implementation
- Mini-map rendering
- River mesh generation
- Territory border rendering
- External asset integration (Meshy AI)
- Common pitfalls and solutions
hex_project_godot/
├── scripts/
│ ├── HexUtils.gd # Core hex math (grid↔world conversion)
│ ├── HexMetrics.gd # River/elevation calculations
│ ├── HexBorder.gd # Territory border generation
│ ├── TerrainGrid.gd # 3D hex prism terrain renderer
│ ├── TerrainGenerator.gd # Procedural terrain generation
│ ├── TerrainMaterial.gd # PBR material management
│ ├── TerrainMeshBuilder.gd # Mesh construction utilities
│ ├── HeightmapLoader.gd # Heightmap auto-discovery and loading
│ ├── RiverGenerator.gd # River path generation
│ ├── RiverRenderer.gd # Smooth ribbon river meshes
│ └── GameMap.gd # Camera controls, click detection
├── shaders/
│ ├── hex_overlay.gdshader # Selection highlighting
│ ├── river_water.gdshader # Animated river water
│ ├── water_realistic.gdshader # Realistic water with waves
│ ├── terrain_hex.gdshader # Hex terrain rendering
│ └── terrain_continuous.gdshader # Blended terrain
└── assets/
└── maps/ # Place heightmap images here
Uses pointy-top hexagons with odd-row offset coordinates:
Row 0: ⬡ ⬡ ⬡ ⬡ ← Even row: no offset
Row 1: ⬡ ⬡ ⬡ ⬡ ← Odd row: offset right by half hex width
Row 2: ⬡ ⬡ ⬡ ⬡
const OUTER_RADIUS: float = 1.0 # Center to corner
const INNER_RADIUS: float = 0.866 # Center to edge midpoint (sqrt(3)/2)
const X_OFFSET: float = 1.732 # Horizontal spacing (sqrt(3))
const Z_OFFSET: float = 1.5 # Vertical spacingstatic func grid_to_world(grid_pos: Vector2i) -> Vector3:
var x: float
var z: float = grid_pos.y * Z_OFFSET
if grid_pos.y % 2 == 1: # Odd rows offset right
x = (grid_pos.x + 0.5) * X_OFFSET
else:
x = grid_pos.x * X_OFFSET
return Vector3(x, 0.0, z)const TERRAIN_ELEVATION_TIERS: Dictionary = {
"terrain_water_deep": 0,
"terrain_water_shallow": 1,
"terrain_coastal": 2,
"terrain_plains": 3,
"terrain_forest": 3,
"terrain_hills": 4,
"terrain_mountains": 6,
}- Red Blob Games: Hexagonal Grids - Essential hex math reference
- Catlike Coding: Hex Map Tutorial - Unity-focused but concepts transfer
- Godot 4 Documentation
MIT License - See LICENSE.md

