使用2D Raycast检测地面碰撞时物体与地面穿模如何解决
问题核心原因
- 你当前的2D射线检测设置了检测距离为0,只有当射线起点刚好和地面碰撞体重叠时才会触发检测,下落速度过快时,单帧下落位移超过了碰撞体的半高,射线完全错过地面,导致重力持续叠加直接穿模,属于典型的物理检测「隧道效应」问题。
- 没有对下落位移做预判处理,就算检测到碰撞也只是停止下落,残留的位移余量还是会导致穿模。
具体修复方案
- 把射线的检测长度调整为当前帧下落位移 + 碰撞体下半部分的偏移量,提前预判接下来的位移路径上会不会碰到地面
- 如果检测到碰撞,直接把角色位置对齐到地面,抵消多余的下落位移
- 条件允许可以额外在碰撞体左右边缘各加一条射线,避免边缘位置检测失效
修复后的参考代码:
public class PlayerMove : MonoBehaviour { Transform _tr; [SerializeField] float speed = 4; [SerializeField] float gravity = 9.81f; [SerializeField] LayerMask mask; // 角色碰撞体半高,可手动填写也可动态获取 [SerializeField] float colliderHalfHeight = 0.5f; float xAxe; void Awake() { _tr = GetComponent<Transform>(); // 如果用BoxCollider2D可以动态获取半高,不用手动填 // BoxCollider2D col = GetComponent<BoxCollider2D>(); // colliderHalfHeight = col.size.y / 2 * _tr.localScale.y; } void Update() { xAxe = Input.GetAxis("Horizontal"); _tr.position += Vector3.right * xAxe * speed * Time.deltaTime; } void FixedUpdate() { // 先计算当前帧预计的下落位移 float fallDistance = gravity * Time.fixedDeltaTime; Vector2 rayOrigin = _tr.position; // 射线长度 = 半高 + 预计下落距离,覆盖完整的移动路径 RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.down, colliderHalfHeight + fallDistance, mask); if (hit.collider == null) { // 无碰撞,正常下落 _tr.position += Vector3.down * fallDistance; } else { // 检测到碰撞,直接对齐到地面位置 _tr.position = new Vector3(_tr.position.x, hit.point.y + colliderHalfHeight, _tr.position.z); } } }
内容的提问来源于stack exchange,提问作者Giuseppe
相关产品推荐
相关产品推荐

