Node2D
2026/4/14大约 6 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — Node2D
Node2D
节点继承关系
继承链:Node → CanvasItem → Node2D
定义
Node2D 继承自 CanvasItem,是所有 2D 节点的基类。它在 CanvasItem 基础上增加了 2D 空间变换:位置(Position)、旋转(Rotation)、缩放(Scale)和变换矩阵(Transform)。
一句话理解:Node2D = "能看见" + "能在 2D 平面上移动、旋转、缩放"。它是 2D 游戏中绝大多数节点的"起点"。
打个比方:如果说 CanvasItem 是一张有透明塑料板的档案卡,那 Node2D 就是在这张卡片上加了一个定位针。你可以把这张卡片钉在软木板的任何位置(位置)、旋转任意角度(旋转)、放大或缩小(缩放)。所有 2D 游戏里的角色、敌人、子弹、道具,都是在这个"带定位针的卡片"基础上发展出来的。
节点用途
- 作为 2D 场景的容器,组织一组 2D 子节点
- 提供位置、旋转、缩放等 2D 空间变换
- 实现角色的移动、转向等基本行为
- 管理局部坐标和全局坐标之间的转换
使用场景
典型场景
- 2D 场景根节点:一个 2D 关卡的根节点通常是
Node2D,下面放置地图、角色、道具等。 - 空容器节点:在角色场景中用一个
Node2D作为根节点,下面放精灵、碰撞体(Collision Shape)等子节点。移动这个Node2D就能让整个角色一起移动。 - 锚点/标记点:用空
Node2D标记特殊位置,比如巡逻路线的拐点、武器的开火位置等。
不适用场景
常用节点搭配
| 搭配节点 | 用途 | 必需? |
|---|---|---|
| Sprite2D | 显示 2D 图片/精灵 | 视需求 |
| AnimatedSprite2D | 显示 2D 动画精灵 | 视需求 |
| CollisionShape2D | 添加碰撞形状 | 物理交互时 |
| Camera2D | 跟随角色的摄像机 | 视需求 |
| Area2D | 检测区域(触发器) | 视需求 |
生效必备素材/资源
Node2D 本身不需要外部资源。但通常会搭配以下资源使用:
| 资源 | 用途 | 必需? |
|---|---|---|
| Texture2D | 配合 Sprite2D 显示图片 | 显示画面时 |
| Shape2D | 配合 CollisionShape2D 做碰撞 | 物理交互时 |
节点属性与信号
位置与变换属性
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
| Position | Vector2 | (0, 0) | — | 相对于父节点的位置(局部坐标) |
| Rotation | float | 0.0 | — | 旋转角度,单位是弧度(顺时针为正) |
| RotationDegrees | float | 0.0 | — | 旋转角度,单位是度数(更直观) |
| Scale | Vector2 | (1, 1) | — | 缩放比例,(1, 1) 为原始大小 |
| Skew | float | 0.0 | — | 倾斜角度(弧度) |
| TopLevel | bool | false | CanvasItem | 是否忽略父节点变换,直接在画布根上定位 |
| ZIndex | int | 0 | CanvasItem | 绘制顺序,值越大越靠前 |
全局变换属性
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
| GlobalPosition | Vector2 | — | — | 全局坐标位置(相对于场景根) |
| GlobalRotation | float | — | — | 全局旋转角度(弧度) |
| GlobalRotationDegrees | float | — | — | 全局旋转角度(度数) |
| GlobalScale | Vector2 | — | — | 全局缩放 |
| Transform | Transform2D | — | — | 完整的局部变换矩阵 |
| GlobalTransform | Transform2D | — | — | 完整的全局变换矩阵 |
可见性与颜色属性(继承自 CanvasItem)
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
| Visible | bool | true | CanvasItem | 是否可见 |
| Modulate | Color | (1,1,1,1) | CanvasItem | 颜色叠加 |
| SelfModulate | Color | (1,1,1,1) | CanvasItem | 自身颜色叠加 |
| Material | Material | null | CanvasItem | 材质/着色器(Shader) |
通用属性(继承自 Node)
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
| Name | String | — | Node | 节点名称 |
| ProcessMode | ProcessModeEnum | Inherit | Node | 处理模式 |
| Script | Script | null | Node | 附加脚本 |
常用方法
| 方法 | 返回值 | 说明 |
|---|---|---|
MoveToward(Vector2 target, float speed) | Vector2 | 朝目标方向移动指定距离(不会超过目标) |
Translate(Vector2 offset) | void | 基于自身朝向移动(受旋转影响) |
Rotate(float angle) | void | 基于自身旋转指定弧度 |
LookAt(Vector2 target) | void | 朝目标点旋转(自动计算角度) |
ToGlobal(Vector2 localPos) | Vector2 | 局部坐标转全局坐标 |
ToLocal(Vector2 globalPos) | Vector2 | 全局坐标转局部坐标 |
GetAngleTo(Vector2 point) | float | 获取到目标点的角度 |
GetDistanceTo(Node2D node) | float | 获取到另一个节点的距离 |
MoveLocalX(float delta, bool scaled) | void | 沿自身 X 轴移动 |
MoveLocalY(float delta, bool scaled) | void | 沿自身 Y 轴移动 |
SetProcess(bool enabled) | void | 启用/禁用 _Process |
代码示例
基础变换操作
C
using Godot;
public partial class TransformDemo : Node2D
{
public override void _Ready()
{
// 设置位置
var node = GetNode<Node2D>("MyNode");
node.Position = new Vector2(100, 200);
// 旋转 45 度
node.RotationDegrees = 45;
// 缩放为 2 倍
node.Scale = new Vector2(2, 2);
// 水平翻转(镜像)
node.Scale = new Vector2(-1, 1);
}
}GDScript
extends Node2D
func _ready():
# 设置位置
var node = $MyNode as Node2D
node.position = Vector2(100, 200)
# 旋转 45 度
node.rotation_degrees = 45
# 缩放为 2 倍
node.scale = Vector2(2, 2)
# 水平翻转(镜像)
node.scale = Vector2(-1, 1)平滑移动
C
using Godot;
public partial class SmoothMovement : Node2D
{
[Export] public float ExSpeed = 200;
private Vector2 _targetPosition;
public override void _Ready()
{
_targetPosition = new Vector2(500, 300);
}
public override void _Process(double delta)
{
// 平滑移动到目标位置(不会超过目标)
Position = Position.MoveToward(_targetPosition, ExSpeed * (float)delta);
// 基于自身朝向移动(Translate 受旋转影响)
// Translate(new Vector2(ExSpeed * (float)delta, 0));
}
}GDScript
extends Node2D
@export var speed: float = 200
var _target_position: Vector2
func _ready():
_target_position = Vector2(500, 300)
func _process(delta):
# 平滑移动到目标位置(不会超过目标)
position = position.move_toward(_target_position, speed * delta)
# 基于自身朝向移动(translate 受旋转影响)
# translate(Vector2(speed * delta, 0))朝向目标
C
using Godot;
public partial class LookAtDemo : Node2D
{
private Node2D _target;
public override void _Process(double delta)
{
if (_target != null)
{
// 朝目标旋转(常用于炮塔、敌人追踪等)
LookAt(_target.GlobalPosition);
// 计算到目标的角度
float angle = GetAngleTo(_target.GlobalPosition);
GD.Print($"到目标的角度: {Mathf.RadToDeg(angle)}");
// 计算到目标的距离
float distance = GlobalPosition.DistanceTo(_target.GlobalPosition);
GD.Print($"到目标的距离: {distance}");
}
}
}GDScript
extends Node2D
var _target: Node2D
func _process(delta):
if _target:
# 朝目标旋转(常用于炮塔、敌人追踪等)
look_at(_target.global_position)
# 计算到目标的角度
var angle = get_angle_to(_target.global_position)
print("到目标的角度: ", rad_to_deg(angle))
# 计算到目标的距离
var distance = global_position.distance_to(_target.global_position)
print("到目标的距离: ", distance)坐标转换
C
using Godot;
public partial class CoordDemo : Node2D
{
public override void _Ready()
{
// 局部坐标转全局坐标
Vector2 localPos = new Vector2(10, 20);
Vector2 globalPos = ToGlobal(localPos);
GD.Print($"局部 (10,20) -> 全局 ({globalPos})");
// 全局坐标转局部坐标
Vector2 worldPos = new Vector2(500, 300);
Vector2 relativePos = ToLocal(worldPos);
GD.Print($"全局 ({worldPos}) -> 局部 ({relativePos})");
}
}GDScript
extends Node2D
func _ready():
# 局部坐标转全局坐标
var local_pos = Vector2(10, 20)
var global_pos = to_global(local_pos)
print("局部 (10,20) -> 全局 ", global_pos)
# 全局坐标转局部坐标
var world_pos = Vector2(500, 300)
var relative_pos = to_local(world_pos)
print("全局 ", world_pos, " -> 局部 ", relative_pos)