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

Unity角色已做接地检测仍可在空中按Space键二次跳高问题求助

问题原因分析
  • 缺少碰撞退出的状态重置:你仅在OnCollisionStay中把isGrounded设为true,但角色离开地面时没有对应的OnCollisionExit逻辑把isGrounded改回false,只要角色和地面有过一次接触后,isGrounded会一直保持true状态,自然可以无限跳跃。
  • 起跳后状态被覆盖:Update的执行顺序和物理帧FixedUpdate不同步,你在按下空格后立即把isGrounded设为false,但同一帧的物理碰撞检测还会执行OnCollisionStay,又把isGrounded改回true,导致判定仍然通过。
  • 地面Tag配置遗漏:场景中3个地面对象如果有任意一个没有配置Ground标签,或者角色碰撞体和其他对象产生了误碰撞,也会导致接地判定异常。
修复方案

直接替换为如下修改后的代码即可:

public bool useCharacterForward = false;
public bool lockToCameraForward = false;
public float turnSpeed = 10f;
public KeyCode sprintJoystick = KeyCode.JoystickButton2;
public KeyCode sprintKeyboard = KeyCode.Space;
public bool useJump = false;
public Vector3 jump;
public float jumpImpulse;
// 起跳后接地冷却,避免刚起跳时的碰撞误判
public float jumpCoolDown = 0.1f;

private float turnSpeedMultiplier;
private float speed = 0f;
private float direction = 0f;
private bool isSprinting = false;
private Animator anim;
private Vector3 targetDirection;
private Vector2 input;
private Quaternion freeRotation;
private Camera mainCamera;
private float velocity;
private bool isGrounded;
private Rigidbody rb;
private float coolDownTimer;

// Use this for initialization
void Start()
{
    anim = GetComponent<Animator>();
    mainCamera = Camera.main;
    rb = GetComponent<Rigidbody>();
    jump = new Vector3(0.0f, 2.0f, 0.0f);
    coolDownTimer = 0f;
}

private void Update()
{
    // 冷却时间计时
    if (coolDownTimer > 0)
    {
        coolDownTimer -= Time.deltaTime;
    }
    // 判定条件增加冷却判断
    if (Input.GetKeyDown(KeyCode.Space) && isGrounded && useJump && coolDownTimer <=0)
    {
        rb.AddForce(jump * jumpImpulse, ForceMode.Impulse);
        isGrounded = false;
        // 起跳后启动冷却,短时间内不触发接地判定
        coolDownTimer = jumpCoolDown;
    }
}

private void OnCollisionStay(Collision collision)
{
    // 冷却时间结束后再更新接地状态
    if (coolDownTimer <=0 && collision.gameObject.tag == "Ground")
    {
        isGrounded = true;
    }
}

// 补全碰撞退出逻辑,离开地面立即重置接地状态
private void OnCollisionExit(Collision collision)
{
    if (collision.gameObject.tag == "Ground")
    {
        isGrounded = false;
    }
}
额外优化建议
  • 如果想进一步提升判定可靠性,可以替换碰撞检测为射线检测:在角色胶囊体底部向下发射长度略大于胶囊底部到中心距离的短射线,判断是否命中地面,不受碰撞帧同步的影响。
  • 检查所有地面对象的Tag配置,确保都已设置为Ground,同时检查角色是否有其他额外碰撞体导致误触。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:27:05