在 Unity 中,各种 Cast
方法是物理检测的核心工具,用于实现射线检测、体积检测、形状投影检测等功能。以下是 Unity 中常用的 Cast
方法及其应用场景,涵盖 3D 和 2D 物理系统。
1. Raycast(射线检测)
用途:检测一条射线是否与场景中的物体发生碰撞(点对点的线性检测)。
适用场景:射击、点击交互、视线检测、地面检测等。
3D 物理系统:
// 基础用法
if (Physics.Raycast(origin, direction, out RaycastHit hit, maxDistance, layerMask)) {
Debug.Log("击中物体: " + hit.collider.name);
}
// 示例:从摄像机发射射线检测鼠标点击
void Update() {
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit)) {
Debug.Log("点击对象: " + hit.collider.name);
}
}
}
2D 物理系统:
RaycastHit2D hit = Physics2D.Raycast(origin, direction, maxDistance, layerMask);
if (hit.collider != null) {
Debug.Log("2D 击中: " + hit.collider.name);
}
2. SphereCast(球体投射检测)
用途:沿着射线方向投射一个球体,检测路径上的碰撞(避免物体移动时“穿透”其他物体)。
适用场景:角色移动碰撞预测、子弹体积检测。
3D 物理系统:
if (Physics.SphereCast(origin, radius, direction, out RaycastHit hit, maxDistance, layerMask)) {
Debug.Log("球体击中: " + hit.collider.name);
}
2D 物理系统(通过组合实现):
// 2D 中无直接 SphereCast,可用 CircleCast 替代
RaycastHit2D hit = Physics2D.CircleCast(origin, radius, direction, maxDistance, layerMask);
if (hit.collider != null) {
Debug.Log("2D 圆形检测: " + hit.collider.name);
}
3. BoxCast(盒子投射检测)
用途:沿着方向投射一个盒子,检测路径上的碰撞。
适用场景:区域攻击判定、物体移动时的体积检测。
3D 物理系统:
Vector3 halfExtents = new Vector3(1, 1, 1); // 盒子的半长
if (Physics.BoxCast(center, halfExtents, direction, out RaycastHit hit, Quaternion.identity, maxDistance, layerMask)) {
Debug.Log("盒子击中: " + hit.collider.name);
}
2D 物理系统:
RaycastHit2D hit = Physics2D.BoxCast(origin, size, 0, direction, maxDistance, layerMask);
if (hit.collider != null) {
Debug.Log("2D 盒子检测: " + hit.collider.name);
}
4. CapsuleCast(胶囊体投射检测)
用途:沿着方向投射一个胶囊体,检测路径上的碰撞(常用于角色控制器)。
适用场景:角色移动时的碰撞预测。
3D 物理系统:
float radius = 0.5f;
float height = 2f;
if (Physics.CapsuleCast(point1, point2, radius, direction, out RaycastHit hit, maxDistance, layerMask)) {
Debug.Log("胶囊体击中: " + hit.collider.name);
}
5. Overlap 检测(体积重叠检测)
用途:检测某个区域内的所有碰撞体,不依赖方向,直接检查重叠。
适用场景:爆炸范围检测、区域触发器。
3D 物理系统:
// SphereOverlap
Collider[] colliders = Physics.OverlapSphere(center, radius, layerMask);
foreach (Collider col in colliders) {
Debug.Log("球体范围内物体: " + col.name);
}
// BoxOverlap
Collider[] boxColliders = Physics.OverlapBox(center, halfExtents, Quaternion.identity, layerMask);
2D 物理系统:
Collider2D[] colliders = Physics2D.OverlapCircleAll(origin, radius, layerMask);
foreach (Collider2D col in colliders) {
Debug.Log("2D 圆形范围内物体: " + col.name);
}
6. Linecast(线段检测)
用途:检测两点之间线段上的碰撞(等同于 Raycast
,但起点和终点明确)。
适用场景:两点间直线碰撞检测。
3D 物理系统:
if (Physics.Linecast(start, end, out RaycastHit hit, layerMask)) {
Debug.Log("线段击中: " + hit.collider.name);
}
2D 物理系统:
RaycastHit2D hit = Physics2D.Linecast(start, end, layerMask);
if (hit.collider != null) {
Debug.Log("2D 线段击中: " + hit.collider.name);
}
7. 通用参数说明
所有 Cast
方法的共性参数:
-
layerMask
:过滤检测的层级(优化性能)。 -
maxDistance
:检测的最大距离。 -
QueryTriggerInteraction
:是否检测触发器(Ignore
或Collide
)。
8. 性能优化建议
-
分层过滤:始终使用
layerMask
减少不必要的检测。 -
避免高频检测:在
Update
中频繁调用Cast
可能导致性能问题。 -
选择合适方法:根据需求选择最轻量的检测(如
Raycast
比SphereCast
高效)。 -
缓存结果:复用检测结果,避免重复计算。
9. 常见问题
-
射线方向未归一化:
direction
需是单位向量(normalized
)。 -
忽略触发器:检查
QueryTriggerInteraction
参数。 -
2D/3D 混淆:注意
Physics
(3D)和Physics2D
(2D)命名空间的区别。
通过合理使用这些 Cast
方法,可以实现复杂的物理交互逻辑(如角色移动、攻击判定、弹道模拟等)。具体选择哪种方法,取决于检测的形状需求和性能成本。
(来自DeepSeek回答,后续尝试测试)