Unity网格生成中如何实现元胞自动机的Tile邻居分配
零物理开销的Tile邻居分配实现方案
核心逻辑:基于规则网格的坐标映射关系,跳过所有物理检测流程,通过二维数组直接建立「网格坐标-Tile实例」的一一对应关系,所有邻居查找为O(1)时间复杂度,性能远高于射线/球体检测方案。
第一步:调整存储结构
你当前代码使用无坐标映射的List<GameObject>存储Tile实例,无法直接通过网格坐标快速定位到对应位置的Tile,这是实现邻居分配的核心障碍。需要新增与地图维度完全匹配的二维数组存储Tile实例:
- 在
WorldGenerator类中,新增字段:public Tile[,] tileGrid; - 在
RandomlyFillMap方法初始化mapFilled的同时,完成tileGrid的实例化:tileGrid = new Tile[mapSize, mapSize];
第二步:实例化Tile时同步写入网格存储
修改GenerateStartingGrid方法中Tile实例化后的逻辑,将生成的Tile绑定到对应网格坐标的位置:
// 原有实例化代码保持不变 Vector3 tilePosition = new Vector3(-mapSize / 2 + x, 0, -mapSize / 2 + y); GameObject newTile = Instantiate(tile, tilePosition, Quaternion.Euler(Vector3.right * 90f)) as GameObject; newTile.transform.SetParent(transform, false); // 替换原有tiles.Add的逻辑 Tile currentTile = newTile.GetComponent<Tile>(); tileGrid[x, y] = currentTile;
第三步:完成邻居分配逻辑
四个方向的邻居完全通过坐标偏移计算得到,全程无物理调用。需要注意两个边界规则:
- 当偏移后的坐标超出
0 ~ mapSize-1的范围时,对应方向的邻居保持为null - 偏移方向可以根据你实际的Tile摆放朝向调整(比如上方向如果对应Z轴负方向,就把对应偏移值从
+1改成-1)
完整的AssignTileNeighbors方法实现:
void AssignTileNeighbors() { for (int x = 0; x < mapSize; x++) { for (int y = 0; y < mapSize; y++) { // 当前坐标无Tile则跳过 Tile currentTile = tileGrid[x, y]; if (currentTile == null) continue; // 分配上方向邻居(y+1位置) if (y + 1 < mapSize) { currentTile.neighbor_UP = tileGrid[x, y + 1]?.gameObject; } // 分配下方向邻居(y-1位置) if (y - 1 >= 0) { currentTile.neighbor_DOWN = tileGrid[x, y - 1]?.gameObject; } // 分配右方向邻居(x+1位置) if (x + 1 < mapSize) { currentTile.neighbor_RIGHT = tileGrid[x + 1, y]?.gameObject; } // 分配左方向邻居(x-1位置) if (x - 1 >= 0) { currentTile.neighbor_LEFT = tileGrid[x - 1, y]?.gameObject; } } } }
方案优势
- 无任何物理引擎调用,不需要为Tile挂载碰撞体,完全消除物理检测的性能开销
- 所有查找操作基于数组下标访问,时间复杂度为O(1),即使是1000*1000规模的地图,邻居分配过程也仅需毫秒级耗时
- 逻辑链路清晰,没有隐式依赖,后续修改元胞自动机规则时可以直接通过Tile的邻居字段读取相邻状态,不需要额外查找
- 这是规则网格类游戏的通用成熟方案,没有冗余逻辑,后续扩展八方向邻居、对角邻居时只需要新增对应坐标偏移的判断即可
注意:原代码中的
List<GameObject> tiles可以保留,如果需要遍历全图Tile做批量操作,直接遍历tileGrid中非空的元素即可,不需要额外维护查找逻辑。
内容的提问来源于stack exchange,提问作者Filip Studený
相关产品推荐
相关产品推荐

