ヘックスマップは、六角形のマス目で構成されます。
座標系と移動処理を理解すれば、実装できます。
この記事では、実装方法を詳しく解説します。
✨ この記事でわかること
- ヘックス座標系の理解
- オフセット座標の実装
- キューブ座標の実装
- 隣接タイルの計算
- 実装例とコード

ヘックスマップは、キューブ座標から始めましょう。計算が簡単になり、実装しやすくなります。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
ヘックス座標系の理解

ヘックスマップを実装するうえで、最初に理解しておきたいのが「座標系」です。
四角いマス(グリッド)とは違い、六角形のマスはそのまま2次元座標に当てはめると、計算が複雑になりがちです。
そこで、ヘックスマップ専用の座標系を使ってマスの位置を管理します。
ここでは、代表的なヘックス座標系の種類と、それぞれの特徴を整理していきます。
座標系の種類
ヘックスマップでは、主に以下の3つの座標系が使われます。
それぞれ「何を重視するか」によって向き・不向きがあります。
ヘックス座標系の代表的な種類
- オフセット座標
2次元配列(行・列)で管理する方法です。
見た目は分かりやすく、マップを配列で扱いたい場合に向いています。 - キューブ座標
q・r・sの3つの軸を使って管理する方法です。
少し特殊に見えますが、距離計算や隣接マスの判定が非常にシンプルになります。 - 軸座標
キューブ座標から1軸を省略した考え方です。
内部的にはキューブ座標を使うことが多く、理解用として登場します。
この記事では、計算の分かりやすさと実装の安定性を重視し、
最終的にキューブ座標を中心に解説していきます。
キューブ座標の基本
キューブ座標は、六角形のマスを3次元の座標として扱う考え方です。
ポイントは、「実際に3D空間で使う」というよりも、計算を楽にするための概念だという点です。
キューブ座標では、以下の3つの値を使います。
- q:X方向の軸
- r:Y方向の軸
- s:Z方向の軸
そして最も重要なルールが、「q + r + s = 0 になるように管理する」という制約です。
このルールを守ることで、距離計算や隣接マスの判定がシンプルになります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using UnityEngine; [System.Serializable] public struct HexCoord { public int q; // X軸 public int r; // Y軸 public int s; // Z軸(q + r + s = 0) public HexCoord(int q, int r, int s) { this.q = q; this.r = r; this.s = s; } public static HexCoord operator +(HexCoord a, HexCoord b) { return new HexCoord(a.q + b.q, a.r + b.r, a.s + b.s); } public static HexCoord operator -(HexCoord a, HexCoord b) { return new HexCoord(a.q - b.q, a.r - b.r, a.s - b.s); } } |
この構造体を使うことで、ヘックスマップ上の位置を1つの座標データとして扱えます。
また、演算子(+ や -)を定義しているため、「隣のマスへ移動する」「2点間の差を求める」といった処理も直感的に書けます。
まずは、「q + r + s = 0 を必ず守る」という点を意識して、キューブ座標に慣れていきましょう。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
オフセット座標の実装

オフセット座標は、ヘックスマップを2次元配列として扱いたい場合に便利な方法です。
Unityの配列管理や、タイルマップ的な発想に慣れている方にとっては、最も直感的に感じられるでしょう。
ここでは、「配列のインデックス」と「ワールド座標」をどう結びつけるかに注目しながら、オフセット座標の実装例を見ていきます。
オフセット座標システム
オフセット座標では、マップを「列(col)」と「行(row)」で管理します。
ただし、六角形のマスは縦横がきれいに揃わないため、列ごとに位置をずらす処理が必要になります。
以下のコードでは、「偶数列と奇数列で、Z方向の位置をずらす」ことで、六角形が正しく並ぶように調整しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class OffsetHexSystem : MonoBehaviour { public int width = 20; public int height = 20; public float hexSize = 1f; private TileData[,] grid; public Vector3 GetWorldPosition(int col, int row) { float x = col * hexSize * 1.5f; float z = row * hexSize * Mathf.Sqrt(3f) + (col % 2) * hexSize * Mathf.Sqrt(3f) / 2f; return new Vector3(x, 0, z); } public Vector2Int GetOffsetPosition(Vector3 worldPos) { // ワールド座標からオフセット座標に変換 // 実装は省略 return Vector2Int.zero; } } |
この GetWorldPosition メソッドが、「配列の位置 → 実際のマップ上の位置」を変換する役割を担っています。
特に重要なのは、以下の2点です。
- X方向は、六角形の横幅に合わせて 1.5倍 している
- 列番号(col)が奇数か偶数かで、Z方向の位置をずらしている
このずらし処理があることで、ヘックスマップ特有の「互い違いに並ぶ形」を再現できます。
なお、GetOffsetPosition のように、ワールド座標から配列インデックスへ逆変換する処理は、計算がやや複雑になるため、ここでは省略しています。
オフセット座標は、「見た目は分かりやすいが、計算処理は増えやすい」という特徴があります。
マップ管理をシンプルにしたい場合に、適した方法と言えるでしょう。

オフセット座標は、配列管理と相性が良いのが魅力です。
ただし、距離計算や隣接判定は工夫が必要になる点を覚えておきましょう。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
キューブ座標の実装

キューブ座標は、ヘックスマップの中でも計算処理に強い座標系です。
見た目は少し複雑に感じるかもしれませんが、実際の処理はシンプルで、移動・距離・隣接判定をまとめて扱いやすくなります。
ここでは、キューブ座標を使ってマップを管理し、ワールド座標と相互に変換するための基本的な実装方法を確認していきます。
キューブ座標システム
このシステムでは、タイルを HexCoord で管理し、各ヘックスを 辞書(Dictionary) に登録しています。
2次元配列とは異なり、必要なタイルだけを管理できるため、広いマップや不規則な形状のマップにも対応しやすくなります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public class CubeHexSystem : MonoBehaviour { public float hexSize = 1f; private Dictionary<HexCoord, TileData> hexMap = new Dictionary<HexCoord, TileData>(); public Vector3 GetWorldPosition(HexCoord hex) { float x = hexSize * (Mathf.Sqrt(3f) * hex.q + Mathf.Sqrt(3f) / 2f * hex.r); float z = hexSize * (3f / 2f * hex.r); return new Vector3(x, 0, z); } public HexCoord GetHexCoord(Vector3 worldPos) { float q = (Mathf.Sqrt(3f) / 3f * worldPos.x - 1f / 3f * worldPos.z) / hexSize; float r = (2f / 3f * worldPos.z) / hexSize; return HexRound(q, r); } HexCoord HexRound(float q, float r) { float s = -q - r; int qInt = Mathf.RoundToInt(q); int rInt = Mathf.RoundToInt(r); int sInt = Mathf.RoundToInt(s); float qDiff = Mathf.Abs(qInt - q); float rDiff = Mathf.Abs(rInt - r); float sDiff = Mathf.Abs(sInt - s); if (qDiff > rDiff && qDiff > sDiff) { qInt = -rInt - sInt; } else if (rDiff > sDiff) { rInt = -qInt - sInt; } return new HexCoord(qInt, rInt, -qInt - rInt); } } |
GetWorldPosition は、キューブ座標 → ワールド座標へ変換するための処理です。q と r を使って位置を計算し、ヘックスを正しい間隔で配置しています。
一方、GetHexCoord は、ワールド座標 → キューブ座標へ変換する処理です。
ここでは、まず小数の座標を求めたあと、最も近いヘックスに丸めています。
この丸め処理を担当しているのが HexRound メソッドです。q・r・s の合計が 0 になるように調整することで、キューブ座標のルールを正しく保っています。
キューブ座標を使う最大のメリットは、距離計算や隣接タイル判定をシンプルに書けることです。
このあと解説する移動処理や範囲計算でも、その強みが活きてきます。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
隣接タイルの計算

隣接タイルの計算は、移動処理に重要です。
実装方法を紹介します。
隣接タイル計算システム
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
public class HexNeighborSystem : MonoBehaviour { // 6方向のベクトル private static readonly HexCoord[] directions = new HexCoord[] { new HexCoord(1, 0, -1), // 右 new HexCoord(1, -1, 0), // 右上 new HexCoord(0, -1, 1), // 左上 new HexCoord(-1, 0, 1), // 左 new HexCoord(-1, 1, 0), // 左下 new HexCoord(0, 1, -1) // 右下 }; public HexCoord GetNeighbor(HexCoord hex, int direction) { if (direction < 0 || direction >= 6) { return hex; } return hex + directions[direction]; } public List<HexCoord> GetAllNeighbors(HexCoord hex) { List<HexCoord> neighbors = new List<HexCoord>(); for (int i = 0; i < 6; i++) { neighbors.Add(GetNeighbor(hex, i)); } return neighbors; } public int GetDistance(HexCoord a, HexCoord b) { HexCoord diff = a - b; return (Mathf.Abs(diff.q) + Mathf.Abs(diff.r) + Mathf.Abs(diff.s)) / 2; } } |
このコードで、隣接タイル計算が実装できます。
6方向の隣接タイルを取得できます。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
実装例:完全なヘックスマップシステム

実際に使える、完全なヘックスマップシステムの実装例を紹介します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
using UnityEngine; public class CompleteHexMapSystem : MonoBehaviour { [Header("システム")] public CubeHexSystem hexSystem; public HexNeighborSystem neighborSystem; public void MoveUnit(Unit unit, HexCoord targetHex) { // 距離をチェック HexCoord currentHex = unit.hexPosition; int distance = neighborSystem.GetDistance(currentHex, targetHex); if (distance <= unit.moveRange) { unit.hexPosition = targetHex; unit.transform.position = hexSystem.GetWorldPosition(targetHex); } } public List<HexCoord> GetMovableHexes(Unit unit) { List<HexCoord> movableHexes = new List<HexCoord>(); HexCoord center = unit.hexPosition; // 移動範囲内のヘックスを取得 for (int q = -unit.moveRange; q <= unit.moveRange; q++) { for (int r = -unit.moveRange; r <= unit.moveRange; r++) { HexCoord checkHex = center + new HexCoord(q, r, -q - r); int distance = neighborSystem.GetDistance(center, checkHex); if (distance <= unit.moveRange) { movableHexes.Add(checkHex); } } } return movableHexes; } } |
このコードで、完全なヘックスマップシステムが実装できます。
座標変換、隣接計算、移動処理を統合しています。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
よくある質問(FAQ)

Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
まとめ

ヘックスマップは、キューブ座標から始めましょう。
計算が簡単になり、実装しやすくなります。
✅ 今日から始める3ステップ
- ステップ1:キューブ座標を実装する(所要2時間)
- ステップ2:座標変換を実装する(所要3時間)
- ステップ3:隣接タイル計算を実装する(所要2時間)
本格的にUnityを学びたい方は、Unity入門の森で実践的なスキルを身につけましょう。
あなたのペースで、少しずつ進めていけば大丈夫です。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる



コメント