You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中Raycast离开碰撞体后仍误检测碰撞的问题求助

Unity跑酷游戏Raycast地面检测误判问题

我正在开发一门认证课程的Unity无限跑酷游戏,为限制角色仅在地面时可跳跃,从角色脚部发射短距离Raycast,检测到碰撞则判定为grounded允许跳跃,否则禁止跳跃。

但当角色未跳跃直接跑下平台时,Raycast在下方无碰撞体的情况下仍持续检测到碰撞,导致角色可空中跳跃。这并非短暂的Coyote Time,直到角色移动到另一平台上方时才停止误检测。平台碰撞体未超出视觉范围,我已尝试调整碰撞体、修改平台碰撞设置、缩短Raycast检测距离及重写判断逻辑,但问题仍未解决。

以下是跳跃与Raycast相关代码:

public class Player : MonoBehaviour
{
    [SerializeField] Rigidbody2D rb;
    [SerializeField] float jumpForce = 5.0f;
    [SerializeField] Transform raycastOrigin;
    [SerializeField] bool isGrounded;

    void Update()
    {
        if (isGrounded == true)
        {
            Debug.DrawRay(raycastOrigin.position, Vector2.down, Color.green);
            if (Input.GetKeyDown(KeyCode.Space))
            {
                rb.AddForce(new Vector2(0, jumpForce), ForceMode2D.Impulse); 
            }
        } else
        {
            Debug.DrawRay(raycastOrigin.position, Vector2.down, Color.red);
        }

        RaycastHit2D hit = Physics2D.Raycast(raycastOrigin.position, Vector2.down); //Shoot a raycast down to tell if the player is on the ground.
        
        if(hit.collider != null) // check if the Raycast is hitting anything
        {
            if (hit.distance < 0.01f) // If the thing the raycast has hit is really close to the origin
            {
                isGrounded = true;
            } else {
                isGrounded = false;
            }
            Debug.Log(hit.transform.name);
        }
        
    }
}

问题核心原因

  1. Raycast无距离限制:当前Physics2D.Raycast只传入起点和方向,默认检测无限远,可能误触场景中下方的其他碰撞体,甚至角色自身的碰撞体。
  2. 未处理无碰撞场景:当Raycast完全没检测到物体时,isGrounded不会被更新,会保持之前的true状态,导致悬空后仍能跳跃。
  3. 检测距离阈值过小:0.01f的距离容错率极低,角色微小的位置偏移就会导致检测失效或误判。

修复方案

方案1:限制Raycast检测范围并排除自身

指定合理的检测距离,同时忽略角色自身的碰撞体,避免自检测:

public class Player : MonoBehaviour
{
    [SerializeField] Rigidbody2D rb;
    [SerializeField] float jumpForce = 5.0f;
    [SerializeField] Transform raycastOrigin;
    [SerializeField] bool isGrounded;
    [SerializeField] float groundCheckDistance = 0.1f; // 设置合理的检测距离

    void Update()
    {
        if (isGrounded)
        {
            Debug.DrawRay(raycastOrigin.position, Vector2.down * groundCheckDistance, Color.green);
            if (Input.GetKeyDown(KeyCode.Space))
            {
                rb.AddForce(new Vector2(0, jumpForce), ForceMode2D.Impulse); 
            }
        } 
        else
        {
            Debug.DrawRay(raycastOrigin.position, Vector2.down * groundCheckDistance, Color.red);
        }

        // 生成忽略自身层的掩码
        int ignoreSelfMask = ~(1 << gameObject.layer);
        RaycastHit2D hit = Physics2D.Raycast(raycastOrigin.position, Vector2.down, groundCheckDistance, ignoreSelfMask);
        
        // 处理所有检测情况,包括无碰撞的场景
        if(hit.collider != null)
        {
            isGrounded = true;
            Debug.Log(hit.transform.name);
        }
        else
        {
            isGrounded = false;
        }
    }
}

方案2:改用CircleCast提升检测稳定性

Raycast单点检测容易受角色位置偏移影响,圆形检测可以覆盖脚部周围区域,更适合地面判定:

public class Player : MonoBehaviour
{
    [SerializeField] Rigidbody2D rb;
    [SerializeField] float jumpForce = 5.0f;
    [SerializeField] Transform raycastOrigin;
    [SerializeField] bool isGrounded;
    [SerializeField] float groundCheckRadius = 0.05f;
    [SerializeField] LayerMask groundLayer; // 给地面单独设置Layer

    void FixedUpdate() // 物理检测移到FixedUpdate同步物理帧
    {
        // 圆形检测脚部周围的地面
        RaycastHit2D hit = Physics2D.CircleCast(raycastOrigin.position, groundCheckRadius, Vector2.down, 0f, groundLayer);
        isGrounded = hit.collider != null;

        // 绘制调试图形
        if(isGrounded)
        {
            Debug.DrawCircle(raycastOrigin.position, groundCheckRadius, Color.green);
        }
        else
        {
            Debug.DrawCircle(raycastOrigin.position, groundCheckRadius, Color.red);
        }
    }

    void Update()
    {
        if (isGrounded && Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(new Vector2(0, jumpForce), ForceMode2D.Impulse); 
        }
    }
}

额外优化建议

  • 给地面单独创建Ground层,检测时只针对该层,避免误触其他物体。
  • 将物理检测逻辑移到FixedUpdate中,和Unity物理更新帧同步,减少帧率波动导致的误判。

内容的提问来源于stack exchange,提问作者Sam Grant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 09:51:17