Unity中按住Shift实现玩家冲刺/加速的问题求助及代码修复
修复玩家冲刺速度叠加与无法恢复的问题
你的核心问题是直接修改了walkSpeed变量且未做合理重置:每次按住Shift时,Update循环都会执行walkSpeed += sprintMultiplier,导致速度持续叠加;松开Shift后没有把速度还原回初始值,所以玩家一直保持高速。
以下是两种可靠的修复方案:
方案一:保留基础速度,动态计算移动速度(推荐)
这种方法不会修改原始的行走速度变量,而是根据冲刺状态动态计算当前移动速度,从根源避免叠加和重置问题。
修改后的完整代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public CharacterController controller; public float walkSpeed = 10f; // 基础行走速度,全程不直接修改 public bool isSprinting; public float sprintMultiplier = 2f; // 建议设为2,代表冲刺速度是行走的2倍 public float gravity = -9.81f; public float jump = 1f; public Transform groundCheck; public float groundDistance = 0.4f; public LayerMask groundMask; Vector3 velocity; bool isGrounded; void Update() { isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask); if (isGrounded && velocity.y < 0) { velocity.y = -2f; } // 简化冲刺状态判断 isSprinting = Input.GetKey(KeyCode.LeftShift); // 移动计算:根据冲刺状态动态调整速度 float x = Input.GetAxis("Horizontal"); float z = Input.GetAxis("Vertical"); Vector3 move = transform.right * x + transform.forward * z; // 关键改动:用基础速度乘以冲刺乘数,而非修改walkSpeed本身 float currentSpeed = isSprinting ? walkSpeed * sprintMultiplier : walkSpeed; controller.Move(move * currentSpeed * Time.deltaTime); // 跳跃逻辑 if (Input.GetButtonDown("Jump") && isGrounded) { velocity.y = Mathf.Sqrt(jump * -2f * gravity); } velocity.y += gravity * Time.deltaTime; controller.Move(velocity * Time.deltaTime); } }
方案二:重置速度回初始值
如果坚持要修改walkSpeed,需要在松开Shift时将其重置回初始值,同时避免每次Update都叠加速度:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public CharacterController controller; public float walkSpeed = 10f; private float baseWalkSpeed; // 专门存储初始行走速度 public bool isSprinting; public float sprintMultiplier = 5f; // 注意数值,因为是直接叠加,建议不要过大 public float gravity = -9.81f; public float jump = 1f; public Transform groundCheck; public float groundDistance = 0.4f; public LayerMask groundMask; Vector3 velocity; bool isGrounded; void Start() { baseWalkSpeed = walkSpeed; // 初始化时保存基础速度 } void Update() { isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask); if (isGrounded && velocity.y < 0) { velocity.y = -2f; } float x = Input.GetAxis("Horizontal"); float z = Input.GetAxis("Vertical"); Vector3 move = transform.right * x + transform.forward * z; controller.Move(move * walkSpeed * Time.deltaTime); if (Input.GetButtonDown("Jump") && isGrounded) { velocity.y = Mathf.Sqrt(jump * -2f * gravity); } velocity.y += gravity * Time.deltaTime; controller.Move(velocity * Time.deltaTime); // 冲刺逻辑修改 if (Input.GetKeyDown(KeyCode.LeftShift)) // 用GetKeyDown只触发一次叠加 { isSprinting = true; walkSpeed += sprintMultiplier; } if (Input.GetKeyUp(KeyCode.LeftShift)) // 松开时重置回基础速度 { isSprinting = false; walkSpeed = baseWalkSpeed; } } }
注意:方案二必须用GetKeyDown和GetKeyUp代替GetKey,否则每次Update都会执行速度叠加;同时要在Start方法中保存初始的walkSpeed,否则重置时会出错。
内容的提问来源于stack exchange,提问作者nice Ice
相关产品推荐
相关产品推荐

