GridMap
2026/4/14大约 5 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — GridMap
GridMap
节点继承关系
继承自 Node3D
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Position | 本地位置(X / Y / Z) |
| 属性 | GlobalPosition | 全局位置 |
| 属性 | Rotation | 旋转角度(欧拉角,弧度) |
| 属性 | Scale | 缩放比例 |
| 属性 | TopLevel | 是否脱离父节点的变换 |
| 方法 | LookAt() | 朝向目标点 |
| 方法 | ToGlobal() | 本地坐标转全局坐标 |
| 方法 | ToLocal() | 全局坐标转本地坐标 |
| 方法 | RotateX/Y/Z() | 绕指定轴旋转 |
继承自 Node
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Name | 节点名称 |
| 属性 | ProcessMode | 处理模式(始终 / 暂停时 / 仅编辑器) |
| 属性 | ProcessPriority | 处理优先级,数字越小越先执行 |
| 信号 | ready | 节点进入场景树并准备就绪 |
| 信号 | tree_entered | 节点进入场景树 |
| 信号 | tree_exited | 节点完全离开场景树 |
| 方法 | GetNode<T>() | 按路径获取子节点 |
| 方法 | AddChild() | 添加子节点 |
| 方法 | RemoveChild() | 移除子节点 |
| 方法 | QueueFree() | 帧结束后释放节点 |
| 方法 | GetParent() | 获取父节点 |
定义
网格地图节点——用网格单元格(就像棋盘上的格子)来快速铺设大场景。每个格子里放一个预设的 Mesh,通过指定格子的坐标来放置物品,非常适合搭建由重复元素组成的大型场景。
打个比方:GridMap 就像 Minecraft 的创造模式——你有一个网格,往格子里放方块就能搭建出城堡、地形、迷宫。只不过 GridMap 不仅可以放方块,还可以放任何你预设好的 3D 模型。
使用频率:★★ 偶尔使用——需要用重复元素快速搭建大场景时使用。
节点用途
- 快速铺设大面积地形(草地、地板、道路)
- 搭建由重复模块组成的关卡
- 创建网格化的迷宫或关卡布局
- 使用 TileSet 风格的工作流搭建 3D 关卡
使用场景
典型场景
- 迷宫游戏:用网格定义迷宫布局
- 策略游戏:铺设网格化的战场
- 开放世界地形:用不同地块铺设大范围地形
- 地牢生成:程序化生成房间和走廊
不适用场景
- 需要精细、不规则的关卡 → 使用手工放置的 MeshInstance3D
- 2D 游戏 → 使用 TileMap 系列节点
常用节点搭配
| 搭配节点 | 用途 | 必需? |
|---|---|---|
| MeshLibrary 资源 | 定义网格中可用的 3D 模型 | 必需 |
| StaticBody3D | 碰撞检测 | 可选 |
典型节点树:
Level (Node3D)
├── GridMap ← 网格地图
└── Player生效必备素材/资源
| 资源 | 类型 | 说明 |
|---|---|---|
| MeshLibrary | MeshLibrary | 赋给 mesh_library 属性,定义每个网格 ID 对应的 3D 模型 |
| TileSet(3D) | TileSet | 在 Godot 4.3+ 中也可使用 TileSet 系统 |
节点属性与信号
网格设置
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
mesh_library | MeshLibrary | — | — | 网格库资源,定义可用的 3D 模型及其碰撞形状 |
cell_size | Vector3i | (2, 2, 2) | — | 每个网格单元的大小 |
cell_octant_size | int | 8 | — | 八叉树单元大小,影响大地图的渲染性能 |
显示设置
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
collision_enabled | bool | true | — | 是否启用碰撞 |
collision_layer | int | 1 | — | 碰撞层 |
collision_mask | int | 1 | — | 碰撞遮罩 |
show_collision | bool | false | — | 在编辑器中是否显示碰撞形状 |
信号
| 信号 | 触发时机 | 继承自 | 说明 |
|---|---|---|---|
| 无自有信号 | — | — | GridMap 自身不发出信号 |
常用方法
| 方法 | 返回值 | 说明 |
|---|---|---|
SetCellItem(coords, item, orientation) | void | 在指定坐标放置模型 |
GetCellItem(coords) | int | 获取指定坐标上的模型 ID |
GetUsedCells() | Vector3i[] | 获取所有已使用格子的坐标 |
GetUsedCellsById(item) | Vector3i[] | 获取指定模型 ID 使用的所有格子坐标 |
Clear() | void | 清空所有格子 |
MapToWorld(coords) | Vector3 | 将网格坐标转换为世界坐标 |
WorldToMap(worldPos) | Vector3i | 将世界坐标转换为网格坐标 |
代码示例
C
using Godot;
/// <summary>
/// 简单的地牢生成器
/// 使用 GridMap 程序化生成房间
/// </summary>
public partial class DungeonGenerator : GridMap
{
// 假设 MeshLibrary 中定义了以下 ID:
// 0 = 空地, 1 = 地板, 2 = 墙壁, 3 = 门
[Export] public int ExRoomIdFloor = 1;
[Export] public int ExRoomIdWall = 2;
[Export] public int ExRoomIdDoor = 3;
[Export] public int ExRoomWidth = 8;
[Export] public int ExRoomHeight = 8;
public override void _Ready()
{
GenerateRoom(0, 0, ExRoomWidth, ExRoomHeight);
}
/// <summary>
/// 生成一个矩形房间
/// </summary>
/// <param name="startX">起始 X 坐标</param>
/// <param name="startZ">起始 Z 坐标</param>
/// <param name="width">房间宽度</param>
/// <param name="height">房间深度</param>
private void GenerateRoom(int startX, int startZ, int width, int height)
{
for (int x = 0; x < width; x++)
{
for (int z = 0; z < height; z++)
{
var cell = new Vector3i(startX + x, 0, startZ + z);
// 边界放墙壁,内部放地板
bool isBorder = x == 0 || x == width - 1 || z == 0 || z == height - 1;
SetCellItem(cell, isBorder ? ExRoomIdWall : ExRoomIdFloor, 0);
}
}
// 在南墙中间放一扇门
var doorCell = new Vector3i(startX + width / 2, 0, startZ + height - 1);
SetCellItem(doorCell, ExRoomIdDoor, 0);
}
}GDScript
## 简单的地牢生成器
## 使用 GridMap 程序化生成房间
extends GridMap
# 假设 MeshLibrary 中定义了以下 ID:
# 0 = 空地, 1 = 地板, 2 = 墙壁, 3 = 门
@export var room_id_floor: int = 1
@export var room_id_wall: int = 2
@export var room_id_door: int = 3
@export var room_width: int = 8
@export var room_height: int = 8
func _ready():
_generate_room(0, 0, room_width, room_height)
## 生成一个矩形房间
func _generate_room(start_x: int, start_z: int, width: int, height: int):
for x in range(width):
for z in range(height):
var cell := Vector3i(start_x + x, 0, start_z + z)
# 边界放墙壁,内部放地板
var is_border := x == 0 or x == width - 1 or z == 0 or z == height - 1
set_cell_item(cell, room_id_wall if is_border else room_id_floor, 0)
# 在南墙中间放一扇门
var door_cell := Vector3i(start_x + width / 2, 0, start_z + height - 1)
set_cell_item(door_cell, room_id_door, 0)使用建议
- MeshLibrary 需要在编辑器中预先创建,定义好每个网格 ID 对应的模型和碰撞
- GridMap 非常适合程序化生成(Procedural Generation),通过代码随机生成关卡
cell_octant_size影响大地图的性能,默认值 8 适合大多数情况- GridMap 内置了碰撞支持,不需要额外添加 StaticBody3D
- 对于不需要程序化生成的静态场景,直接放置 MeshInstance3D 可能更灵活
