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

Unity角色跳跃计数变量未正确递减的问题求助

问题分析

你的问题根源在于代码逻辑顺序错误:在同一帧中,你先处理了跳跃(将jumpCount减1),随后又因为当前帧角色仍未离开地面(touchingGround为true),执行了重置jumpCount的逻辑,把已经递减的计数又改回了初始值jumpNum。

当jumpNum=1时,跳跃后jumpCount变为0,立刻被重置为1,所以看起来没变化;而当jumpNum≥2时,跳跃后jumpCount变为jumpNum-1,虽然同一帧被重置为jumpNum,但下一帧角色离开地面,touchingGround变为false,jumpCount保持为jumpNum-1,所以还能跳第二次,看起来功能正常,但实际上这是逻辑错误导致的巧合。

修复方案

调整代码逻辑顺序,将重置跳跃计数的逻辑放在跳跃处理之前,同时优化触地检测的准确性,移除无用的updateRunning变量:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BodyMovement : MonoBehaviour
{
    Rigidbody rb; 
    public float jumpHeight = 10;
    public int jumpNum = 1;
    public float speed = 10;
    int jumpCount;
    bool touchingGround = false;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        jumpCount = jumpNum; // 初始化跳跃计数
    }

    void Update()
    {   
        // 优化触地检测:从角色底部发射射线,避免中心检测的误判
        Vector3 rayOrigin = transform.position + Vector3.down * (GetComponent<Collider>().bounds.extents.y - 0.1f);
        touchingGround = Physics.Raycast(rayOrigin, Vector3.down, 0.2f);

        // 触地时重置跳跃计数(放在跳跃处理前)
        if(touchingGround){
            jumpCount = jumpNum;
        }

        // 处理移动
        if(Input.GetKey(KeyCode.D)){
            rb.velocity = new Vector3(speed, rb.velocity.y, 0);
        }else if(Input.GetKey(KeyCode.A)){
            rb.velocity = new Vector3(-speed, rb.velocity.y, 0);   
        }else if(touchingGround){
            rb.velocity = new Vector3(0, rb.velocity.y, 0);
        }

        // 处理跳跃
        if(Input.GetKeyDown(KeyCode.W) && jumpCount > 0){
            rb.AddForce(new Vector3(0, jumpHeight, 0), ForceMode.VelocityChange);
            jumpCount--;
            Debug.Log($"跳跃后剩余次数:{jumpCount}");
        }

        Debug.Log($"Jumpcount:{jumpCount} TouchingGround:{touchingGround}");
    }
}
额外优化建议
  1. 触地检测更可靠:推荐使用OnCollisionStay或OnTriggerStay来检测角色与地面的碰撞,比Raycast更稳定,比如给地面添加Ground标签,然后在碰撞回调中设置touchingGround:

    private void OnCollisionStay(Collision collision)
    {
        if(collision.gameObject.CompareTag("Ground")){
            touchingGround = true;
        }
    }
    
    private void OnCollisionExit(Collision collision)
    {
        if(collision.gameObject.CompareTag("Ground")){
            touchingGround = false;
        }
    }
    

    这种方式不需要每帧发射射线,性能更好,也更准确。

  2. 避免直接修改Velocity:移动时可以使用rb.AddForce配合ForceMode.Acceleration,让移动更符合物理规律,尤其是当角色有其他力作用时(比如重力)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:55:04