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

如何合并移动向量并使用CharacterController.Move()解决斜向移速过快问题

解决第一人称控制器斜向移动超速问题,切换到CharacterController.Move()

嘿,这个问题是向量叠加时的经典小坑!当你同时按下前后和左右方向键时,moveDirectionForward + moveDirectionSide的向量长度会大于1,相当于把两个方向的速度直接叠加,导致斜向移动时实际速度是walkSpeed × √2(大概1.41倍),自然比单一方向移动快很多。

要解决这个问题,我们需要先归一化合并后的移动方向,确保无论怎么组合输入,最终的移动方向长度都是1(或者0,没输入时),再应用速度和时间因子,最后切换到CharacterController.Move()——注意这个方法需要手动处理重力,不像SimpleMove()会自动帮你搞定重力。

下面是修改后的完整代码,每一步都标了注释:

// 新增重力参数,根据你的游戏需求调整数值
public float gravity = 9.81f;
private Vector3 playerVerticalVelocity;

void MovePlayer() { 
    // 获取水平/垂直输入
    float horizontalInput = Input.GetAxis("Horizontal"); 
    float verticalInput = Input.GetAxis("Vertical"); 

    // 1. 先合并方向向量(这里先不乘速度和时间)
    Vector3 moveDirection = transform.forward * verticalInput + transform.right * horizontalInput;

    // 2. 归一化方向,避免斜向移动超速
    // 先判断向量长度是否大于1,防止无输入时归一化出错
    if (moveDirection.magnitude > 1f)
    {
        moveDirection.Normalize();
    }

    // 3. 给方向加上速度和时间因子
    moveDirection *= walkSpeed * Time.deltaTime;

    // 4. 手动处理重力:角色不在地面时,持续叠加重力
    if (!myCharacterController.isGrounded)
    {
        playerVerticalVelocity.y -= gravity * Time.deltaTime;
    }
    else
    {
        // 地面上时重置垂直速度,让控制器保持贴地(-0.1f是防止浮空的小技巧)
        playerVerticalVelocity.y = -0.1f;
    }

    // 5. 把重力的垂直速度合并到最终移动向量里
    moveDirection += playerVerticalVelocity * Time.deltaTime;

    // 6. 用CharacterController.Move()应用移动
    myCharacterController.Move(moveDirection);
}

几个关键细节说明:

  • 归一化的作用:Normalize()会把向量缩放到长度为1,这样不管是前后、左右还是斜向移动,实际移动速度都会稳定在walkSpeed,不会出现超速的情况。加个长度判断是因为当没有输入时,向量长度为0,直接归一化会报错。
  • 重力的手动处理:SimpleMove()内部已经封装了重力逻辑,但Move()更灵活,需要我们自己维护垂直方向的速度。地面时重置垂直速度为-0.1f,是为了让控制器始终检测到地面接触,避免出现浮空的奇怪情况。
  • 为什么换Move():如果你需要自定义移动逻辑(比如冲刺、跳跃的精细控制),Move()比SimpleMove()更适合,它不会自动处理速度的归一化和重力,给了你更多控制权。

内容的提问来源于stack exchange,提问作者Gerte

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:53:01