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; }
关键修改说明
- 修正耐力逻辑:冲刺时减少
currentStamina,恢复时增加;冲刺条件改为currentStamina > 0且不在冷却状态。 - 修复移动叠加:统一计算当前速度,只执行一次移动逻辑,避免速度叠加异常。
- 实现冷却协程:用
IEnumerator实现耐力耗尽后的5秒冷却,冷却期间无法触发冲刺。 - 添加耐力恢复逻辑:单独用
HandleStamina函数处理静置时的耐力恢复,只有满足“不冲刺、不在冷却、耐力未满”三个条件才会恢复。 - 改用Rigidbody移动:用
rb.MovePosition替代直接修改transform.position,遵循Unity物理系统规则,避免物理冲突问题。 - 状态控制优化:增加
isStaminaCooling标记冷却状态,避免重复启动协程导致的逻辑混乱。
内容的提问来源于stack exchange,提问作者K-Afnan
相关产品推荐
相关产品推荐

