Unity 3D FPS角色控制器Dash速度不一致问题求助
3D FPS游戏中Character Controller的恒定Dash速度实现问题
我正在开发一款3D FPS游戏,玩家角色使用Character Controller,未使用Rigidbody。
最初的Dash实现代码
x = Input.GetAxis("Horizontal"); //默认获取WASD输入 z = Input.GetAxis("Vertical"); Vector3 move = transform.right * x + transform.forward * z; //创建移动向量 controller.Move(move * speed * Time.deltaTime); //移动玩家 if (currentDashLength < dashLength ) //在设定时间内冲刺 { currentDashLength += Time.deltaTime; velocity.y = 0; //保持角色在空中 controller.Move(move * Time.deltaTime * dashSpeed); } else { currentDashLength = dashLength; isDashing = false; } if (Input.GetKeyDown(KeyCode.LeftShift) && dashTimer >= 1 && !isCrouching) { isDashing = true; dashTimer -= 1; currentDashLength = 0f; health.GiveIFrames(dashLength); }
问题现象
该Dash功能基本可用,但如果在刚移动时按下Shift触发Dash,Dash效果会明显偏弱。推测是因为此时角色水平速度较低,Move函数的加速度无法让角色达到正常移动时的终端速度。
尝试修复但无效的代码
我尝试通过将Move函数的输入乘以1/角色水平速度来修复,但并未解决问题。修改后的完整代码如下:
float dispX = transform.position.x - posX; //计算自上一帧以来的位置变化,用于计算速度(因为玩家未使用Rigidbody) float dispY = transform.position.y - posY; float dispZ = transform.position.z - posZ; posX = transform.position.x; posY = transform.position.y; posZ = transform.position.z; float horizontalVelocity = Mathf.Sqrt(dispX*dispX + dispZ*dispZ) / Time.deltaTime; x = Input.GetAxis("Horizontal"); //默认获取WASD输入 z = Input.GetAxis("Vertical"); Vector3 move = transform.right * x + transform.forward * z; //创建移动向量 controller.Move(move * speed * Time.deltaTime); //移动玩家 if (currentDashLength < dashLength ) { currentDashLength += Time.deltaTime; velocity.y = 0; if(horizontalVelocity == 0) { Debug.Log("Cannot dash while standing still"); } else { controller.Move(move * Time.deltaTime * dashSpeed * (1 / horizontalVelocity)); } } else { currentDashLength = dashLength; isDashing = false; } if (Input.GetKeyDown(KeyCode.LeftShift) && dashTimer >= 1 && !isCrouching) { isDashing = true; dashTimer -= 1; currentDashLength = 0f; health.GiveIFrames(dashLength); }
求助:如何实现恒定的Dash速度?
解决方案
要实现恒定的Dash速度,核心是在Dash期间直接使用固定的冲刺方向和速度,忽略当前的移动加速度限制,具体调整如下:
- 记录Dash触发时的方向:在按下Shift触发Dash时,立即确定当前的冲刺方向(基于当时的输入或角色朝向),避免后续输入变化影响Dash轨迹。
- Dash期间直接应用恒定速度:在Dash阶段,不再依赖常规移动的
move * speed,而是直接使用预先计算好的冲刺方向乘以固定的dashSpeed,并且要覆盖常规移动的逻辑,避免两者叠加导致速度异常。 - 处理方向归一化:确保冲刺方向是单位向量,保证不同输入组合下速度一致(比如斜向移动时不会因为向量长度大于1导致速度翻倍)。
修改后的核心代码示例:
// 新增变量存储冲刺方向 private Vector3 dashDirection; x = Input.GetAxis("Horizontal"); z = Input.GetAxis("Vertical"); Vector3 move = transform.right * x + transform.forward * z; // 仅在非Dash状态下执行常规移动 if (!isDashing) { if (move.magnitude > 1) move.Normalize(); // 斜向移动归一化,避免速度超标 controller.Move(move * speed * Time.deltaTime); } if (currentDashLength < dashLength ) { currentDashLength += Time.deltaTime; velocity.y = 0; // 使用预先记录的冲刺方向和固定速度 controller.Move(dashDirection * dashSpeed * Time.deltaTime); } else { currentDashLength = dashLength; isDashing = false; } if (Input.GetKeyDown(KeyCode.LeftShift) && dashTimer >= 1 && !isCrouching) { isDashing = true; dashTimer -= 1; currentDashLength = 0f; health.GiveIFrames(dashLength); // 记录冲刺方向,归一化确保速度恒定 dashDirection = move.magnitude > 0 ? move.normalized : transform.forward; // 如果允许静止时冲刺,这里可以处理静止状态下的默认方向(比如角色正前方) }
关键说明
- 分离常规移动与Dash逻辑:Dash期间跳过常规移动,避免两种移动逻辑叠加导致速度不稳定。
- 固定Dash方向:触发Dash时锁定方向,让Dash轨迹更可控,同时保证速度恒定。
- 向量归一化:确保无论玩家是正方向还是斜方向输入,Dash的速度大小都是
dashSpeed,不会因为输入向量长度问题出现速度差异。
内容的提问来源于stack exchange,提问作者Milosz Wedrowski
相关产品推荐
相关产品推荐

