如何合并移动向量并使用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
相关产品推荐
相关产品推荐

