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

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期间直接使用固定的冲刺方向和速度,忽略当前的移动加速度限制,具体调整如下:

  1. 记录Dash触发时的方向:在按下Shift触发Dash时,立即确定当前的冲刺方向(基于当时的输入或角色朝向),避免后续输入变化影响Dash轨迹。
  2. Dash期间直接应用恒定速度:在Dash阶段,不再依赖常规移动的move * speed,而是直接使用预先计算好的冲刺方向乘以固定的dashSpeed,并且要覆盖常规移动的逻辑,避免两者叠加导致速度异常。
  3. 处理方向归一化:确保冲刺方向是单位向量,保证不同输入组合下速度一致(比如斜向移动时不会因为向量长度大于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:15:48