ShapeCast2D
2026/4/14大约 5 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — ShapeCast2D
ShapeCast2D
节点继承关系
继承链:Node → CanvasItem → Node2D → ShapeCast2D
继承自 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() | 获取父节点 |
定义
比射线"更粗"的检测——射线是一条线,ShapeCast 是把一个形状(比如圆、方块)沿着一条路径投射出去。
如果 RayCast2D 是激光笔(一条细线),那 ShapeCast2D 就是手电筒(一个光柱)。它把一个完整的形状从起点沿着一个方向"推"出去,检测沿途碰到了什么。
使用频率:★★ 偶尔使用——在射线不够用的时候使用。
节点用途
- 检测通道宽度是否足够角色通过
- 检测某个形状的路径上有没有障碍物
- 比射线更粗的碰撞检测
使用场景
典型场景
- 通道检测:角色能不能通过一扇窄门
- 碰撞预判:角色下一步移动会不会撞到墙
不适用场景
- 只需一条细线检测 → 使用 RayCast2D 更简单高效
常用节点搭配
| 搭配节点 | 用途 | 必需? |
|---|---|---|
| Node2D(作为父节点) | 位置锚点 | 推荐 |
典型节点树:
Doorway (Node2D)
└── ShapeCast2D ← 用角色形状投射,检测能否通过生效必备素材/资源
| 资源 | 类型 | 说明 |
|---|---|---|
| 碰撞形状(如 CapsuleShape2D) | Shape2D 资源 | 赋给 Shape 属性,定义投射的形状 |
节点属性与信号
核心属性
| 属性 | 类型 | 默认值 | 继承自 | 说明 |
|---|---|---|---|---|
Enabled | bool | false | — | 是否启用 |
Shape | Shape2D | null | — | 投射的形状 |
TargetPosition | Vector2 | (0, -50) | — | 投射目标位置(相对于节点的偏移) |
CollideWithBodies | bool | true | — | 是否检测物理体 |
CollideWithAreas | bool | false | — | 是否检测 Area |
MaxResults | int | 32 | — | 最大检测结果数 |
CollisionMask | uint | 1 | — | 碰撞层掩码 |
ExcludeParent | bool | true | — | 是否排除父节点 |
信号
| 信号 | 触发时机 | 继承自 | 说明 |
|---|---|---|---|
| 无自有信号 | — | — | — |
常用方法
| 方法 | 返回值 | 说明 |
|---|---|---|
IsColliding() | bool | 是否碰到了东西 |
GetCollisionCount() | int | 碰到了多少个物体 |
GetCollider(index) | Object | 获取指定索引的碰撞体 |
GetCollisionPoint(index) | Vector2 | 获取指定索引的碰撞点 |
GetCollisionNormal(index) | Vector2 | 获取指定索引的碰撞法线 |
ForceShapecastUpdate() | void | 强制立即更新检测结果 |
GetClosestCollisionSafeFraction() | float | 获取最近碰撞的安全比例 |
GetClosestCollisionUnsafeFraction() | float | 获取最近碰撞的不安全比例 |
代码示例
C
using Godot;
/// <summary>
/// 用 ShapeCast 检测通道宽度是否足够角色通过
/// 节点结构:Doorway (Node2D) + ShapeCast2D
/// </summary>
public partial class PassageDetector : Node2D
{
private ShapeCast2D _shapeCast;
public override void _Ready()
{
_shapeCast = GetNode<ShapeCast2D>("ShapeCast2D");
_shapeCast.Enabled = true;
// 设置投射形状为一个胶囊(和角色碰撞形状一样大)
var shape = new CapsuleShape2D();
shape.Radius = 16f;
shape.Height = 32f;
_shapeCast.Shape = shape;
// 向下投射,检测路径上有没有障碍物
_shapeCast.TargetPosition = new Vector2(0f, 100f);
}
/// <returns>true = 通道畅通,false = 有障碍物挡路</returns>
public bool IsPassageClear()
{
_shapeCast.ForceShapecastUpdate();
return !_shapeCast.IsColliding();
}
}
/// <summary>
/// 用 ShapeCast 预判角色下一步是否安全
/// </summary>
public partial class MoveSafetyChecker : CharacterBody2D
{
private ShapeCast2D _shapeCast;
public override void _Ready()
{
_shapeCast = GetNode<ShapeCast2D>("ShapeCast2D");
_shapeCast.Enabled = true;
// 使用和角色一样的碰撞形状
var shape = new CapsuleShape2D();
shape.Radius = 8f;
shape.Height = 16f;
_shapeCast.Shape = shape;
}
/// <summary>
/// 检查向某个方向移动是否安全(不会撞墙)
/// </summary>
public bool IsMoveSafe(Vector2 direction, float distance)
{
_shapeCast.TargetPosition = direction * distance;
_shapeCast.ForceShapecastUpdate();
return !_shapeCast.IsColliding();
}
}GDScript
# 用 ShapeCast 检测通道宽度是否足够角色通过
# 节点结构:Doorway (Node2D) + ShapeCast2D
extends Node2D
@onready var shape_cast: ShapeCast2D = $ShapeCast2D
func _ready() -> void:
shape_cast.enabled = true
# 设置投射形状为一个胶囊(和角色碰撞形状一样大)
var shape := CapsuleShape2D.new()
shape.radius = 16.0
shape.height = 32.0
shape_cast.shape = shape
# 向下投射,检测路径上有没有障碍物
shape_cast.target_position = Vector2(0.0, 100.0)
## true = 通道畅通,false = 有障碍物挡路
func is_passage_clear() -> bool:
shape_cast.force_shapecast_update()
return not shape_cast.is_colliding()RayCast vs ShapeCast
- RayCast:一条无限细的线,速度快,适合检测"有没有东西"
- ShapeCast:一个有体积的形状,速度稍慢,适合检测"这个形状能不能通过"
- 如果只需要知道"前面有没有墙",用 RayCast 就够了
- 如果需要知道"角色(有体积的)能不能走过去",用 ShapeCast
