AnimatableBody2D
2026/4/14大约 5 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — AnimatableBody2D
AnimatableBody2D
节点继承关系
继承链:Node → CanvasItem → Node2D → PhysicsBody2D → AnimatableBody2D
继承自 PhysicsBody2D
| 类型 | 名称 | 说明 |
|---|---|---|
| 方法 | MoveAndCollide() | 移动并检测碰撞 |
| 方法 | TestMove() | 测试移动是否会碰撞(不实际移动) |
继承自 Node2D
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Position | 本地位置(相对于父节点) |
| 属性 | GlobalPosition | 全局位置 |
| 属性 | Rotation | 旋转角度(弧度) |
| 属性 | Scale | 缩放比例 |
| 属性 | Skew | 倾斜角度(弧度) |
| 方法 | Rotate() | 旋转指定弧度 |
| 方法 | ToGlobal() | 本地坐标转全局坐标 |
| 方法 | ToLocal() | 全局坐标转本地坐标 |
继承自 CanvasItem
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Visible | 是否可见 |
| 属性 | Modulate | 整体颜色叠加(乘法) |
| 属性 | SelfModulate | 自身颜色叠加(不影响子节点) |
| 属性 | ZIndex | 绘制层级(Z 轴排序) |
| 信号 | visibility_changed | 可见性变化时触发 |
| 方法 | GetGlobalMousePosition() | 获取鼠标全局坐标 |
继承自 Node
| 类型 | 名称 | 说明 |
|---|---|---|
| 属性 | Name | 节点名称 |
| 属性 | ProcessMode | 处理模式(始终 / 暂停时 / 仅编辑器) |
| 属性 | ProcessPriority | 处理优先级,数字越小越先执行 |
| 信号 | ready | 节点进入场景树并准备就绪 |
| 信号 | tree_entered | 节点进入场景树 |
| 信号 | tree_exited | 节点完全离开场景树 |
| 方法 | GetNode<T>() | 按路径获取子节点 |
| 方法 | AddChild() | 添加子节点 |
| 方法 | RemoveChild() | 移除子节点 |
| 方法 | QueueFree() | 帧结束后释放节点 |
| 方法 | GetParent() | 获取父节点 |
定义
通过动画或代码移动的物理体——它会动,但它推动其他物体的方式很"温和",像轻轻推着走,而不是用力撞。
想象你在推一辆停在铁轨上的小车——你慢慢推它走,小车也跟着慢慢动。AnimatableBody2D 就像那个小车:它自己会动(通过动画或代码),但它的运动不会对其他物体产生强烈的冲击力。
它和 StaticBody2D 的区别是:StaticBody 永远不动,AnimatableBody 可以通过动画或代码改变位置。
它和 RigidBody2D 的区别是:RigidBody 由物理引擎控制运动,AnimatableBody 由你(动画/代码)控制运动。
使用频率:★★★ 一般常用——用于特定的移动平台场景。
节点用途
- 通过 AnimationPlayer 驱动的移动平台
- 通过代码改变位置的碰撞体(不希望产生冲击力)
- 电梯、自动门等需要"温和"推动其他物体的场景
使用场景
典型场景
- 动画驱动的移动平台:用 AnimationPlayer 让平台来回移动,站在上面的角色会被平台带着走
- 自动门:门缓缓打开,不会把人弹飞
- 电梯:电梯上升时,站在里面的人跟着上去
不适用场景
- 需要自己精确控制移动的角色 → 使用 CharacterBody2D
- 需要受物理力影响的物体 → 使用 RigidBody2D
- 永远不动的物体 → 使用 StaticBody2D
常用节点搭配
| 搭配节点 | 用途 | 必需? |
|---|---|---|
| CollisionShape2D | 定义碰撞边界 | 必需 |
| AnimationPlayer | 驱动平台的移动动画 | 推荐 |
| Sprite2D | 显示外观 | 推荐 |
典型节点树:
MovingPlatform (AnimatableBody2D)
├── CollisionShape2D
├── Sprite2D
└── AnimationPlayer生效必备素材/资源
| 资源 | 类型 | 说明 |
|---|---|---|
| 碰撞形状 | Shape2D 资源 | 赋给 CollisionShape2D 子节点 |
| 动画资源 | Animation 资源 | 赋给 AnimationPlayer,定义移动路径 |
节点属性与信号
物理属性
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
Bounce | float | 0.0 | — | 弹性系数 |
Friction | float | 1.0 | — | 摩擦系数 |
PhysicsMaterialOverride | PhysicsMaterial | null | — | 自定义物理材质 |
SyncToPhysics | bool | true | — | 是否在物理步后同步位置(保持与动画一致) |
碰撞层
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
CollisionLayer | uint | 1 | CollisionObject2D | 所在碰撞层 |
CollisionMask | uint | 1 | CollisionObject2D | 检测哪些碰撞层 |
信号
| 信号 | 触发时机 | 继承自 | 说明 |
|---|---|---|---|
| 无常用自有信号 | — | — | — |
常用方法
| 方法 | 返回值 | 说明 |
|---|---|---|
GetCollisionExceptions() | GodotArray[Node] | 获取碰撞例外列表 |
AddCollisionExceptionWith(body) | void | 添加碰撞例外 |
RemoveCollisionExceptionWith(body) | void | 移除碰撞例外 |
代码示例
C
using Godot;
/// <summary>
/// 用代码驱动的移动平台
/// 节点结构:MovingPlatform (AnimatableBody2D) + CollisionShape2D + Sprite2D
/// </summary>
public partial class CodeDrivenPlatform : AnimatableBody2D
{
[Export] public float ExMoveSpeed = 100.0f; // 移动速度
[Export] public float ExMoveDistance = 200.0f; // 移动距离
private Vector2 _startPosition;
private float _progress; // 0~1 之间的进度
public override void _Ready()
{
_startPosition = Position;
}
public override void _PhysicsProcess(double delta)
{
float dt = (float)delta;
// 来回移动
_progress += dt * ExMoveSpeed / ExMoveDistance;
// 用 sin 函数实现来回运动
float offset = Mathf.Sin(_progress * Mathf.Tau) * ExMoveDistance;
// 直接修改 Position(AnimatableBody 允许这样做!)
Position = _startPosition + new Vector2(offset, 0f);
}
}GDScript
# 用代码驱动的移动平台
# 节点结构:MovingPlatform (AnimatableBody2D) + CollisionShape2D + Sprite2D
extends AnimatableBody2D
@export var move_speed: float = 100.0 # 移动速度
@export var move_distance: float = 200.0 # 移动距离
var _start_position: Vector2
var _progress: float = 0.0 # 0~1 之间的进度
func _ready() -> void:
_start_position = position
func _physics_process(delta: float) -> void:
# 来回移动
_progress += delta * move_speed / move_distance
# 用 sin 函数实现来回运动
var offset := sin(_progress * TAU) * move_distance
# 直接修改 Position(AnimatableBody 允许这样做!)
position = _start_position + Vector2(offset, 0.0)AnimatableBody vs RigidBody vs CharacterBody
- AnimatableBody:你通过动画/代码直接改位置,物理引擎负责"温和地"推开挡路的物体
- RigidBody:物理引擎控制位置,你通过施力间接影响运动
- CharacterBody:你自己写移动逻辑,引擎帮你处理碰撞(角色不推开其他物体)
