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

Unity C#实现冲刺耗竭静置恢复的Stamina计量器及代码修复求助

Unity耐力冲刺系统问题修复

原代码核心问题

  • 耐力逻辑完全颠倒:冲刺本该消耗耐力(currentStamina减少),你写的却是增加;初始给了满耐力,却限制只有耐力不满时才能冲刺,逻辑完全搞反。
  • 移动叠加错误:不管是否触发冲刺,函数末尾都会执行一次普通移动,导致冲刺时实际速度是sprintSpeed + moveSpeed,远超预期值。
  • 等待逻辑无效:new WaitForSeconds(5f)在普通函数里不会产生等待效果,必须用协程才能实现冷却延迟。
  • 缺少耐力恢复与冷却机制:没写静置时恢复耐力的代码,耐力耗尽后也没有强制冷却的逻辑,不符合“耗尽后需等待恢复才能再次冲刺”的要求。
  • 移动方式不合理:已经获取了Rigidbody,却用transform.position直接修改位置,会绕过物理引擎,导致碰撞、穿模等问题。

修复后的完整代码

private Rigidbody rb;
[SerializeField] private Transform camera;

[Header("移动参数")]
public float moveSpeed = 5f;
public float sprintSpeed = 8f;

[Header("耐力参数")]
public float maxStamina = 5f;
public float staminaConsumeRate = 1f; // 每秒消耗的耐力
public float staminaRecoverRate = 1f; // 每秒恢复的耐力
public float staminaCooldown = 5f; // 耐力耗尽后的冷却时间

private float currentStamina;
private bool isStaminaCooling; // 是否处于耐力冷却状态
private Coroutine staminaRecoverCoroutine;

void Start()
{
    rb = GetComponent<Rigidbody>();
    rb.freezeRotation = true;
    currentStamina = maxStamina;
}

void Update()
{
    Movement();
    HandleStamina();
}

private void Movement()
{
    float movementX = Input.GetAxis("Horizontal");
    float movementZ = Input.GetAxis("Vertical");

    // 基于相机方向计算移动方向,忽略Y轴避免浮空
    Vector3 cameraForward = Vector3.Scale(camera.forward, new Vector3(1, 0, 1)).normalized;
    Vector3 moveDirection = cameraForward * movementZ + camera.right * movementX;

    // 确定当前移动速度
    float currentSpeed = moveSpeed;
    bool canSprint = Input.GetKey(KeyCode.LeftShift) && currentStamina > 0 && !isStaminaCooling;
    
    if (canSprint)
    {
        currentSpeed = sprintSpeed;
        // 消耗耐力,限制最低值为0
        currentStamina -= staminaConsumeRate * Time.deltaTime;
        currentStamina = Mathf.Max(currentStamina, 0);
    }

    // 只有当有输入时才移动,避免空转
    if (moveDirection.magnitude > 0.1f)
    {
        rb.MovePosition(transform.position + moveDirection.normalized * currentSpeed * Time.deltaTime);
    }
}

private void HandleStamina()
{
    // 耐力耗尽且未冷却时,启动冷却协程
    if (currentStamina <= 0 && !isStaminaCooling)
    {
        if (staminaRecoverCoroutine != null)
        {
            StopCoroutine(staminaRecoverCoroutine);
        }
        staminaRecoverCoroutine = StartCoroutine(StaminaCooldownCoroutine());
    }
    // 不在冷却、未冲刺且耐力未满时,恢复耐力
    else if (!isStaminaCooling && !Input.GetKey(KeyCode.LeftShift) && currentStamina < maxStamina)
    {
        currentStamina += staminaRecoverRate * Time.deltaTime;
        currentStamina = Mathf.Min(currentStamina, maxStamina);
    }
}

// 耐力冷却协程,实现延迟恢复
private IEnumerator StaminaCooldownCoroutine()
{
    isStaminaCooling = true;
    yield return new WaitForSeconds(staminaCooldown);
    isStaminaCooling = false;
}

关键修改说明

  1. 修正耐力逻辑:冲刺时减少currentStamina,恢复时增加;冲刺条件改为currentStamina > 0且不在冷却状态。
  2. 修复移动叠加:统一计算当前速度,只执行一次移动逻辑,避免速度叠加异常。
  3. 实现冷却协程:用IEnumerator实现耐力耗尽后的5秒冷却,冷却期间无法触发冲刺。
  4. 添加耐力恢复逻辑:单独用HandleStamina函数处理静置时的耐力恢复,只有满足“不冲刺、不在冷却、耐力未满”三个条件才会恢复。
  5. 改用Rigidbody移动:用rb.MovePosition替代直接修改transform.position,遵循Unity物理系统规则,避免物理冲突问题。
  6. 状态控制优化:增加isStaminaCooling标记冷却状态,避免重复启动协程导致的逻辑混乱。

内容的提问来源于stack exchange,提问作者K-Afnan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 04:47:48