Unity自定义角色物理系统空中移动随视角旋转偏移问题怎么解决?
问题修复方案
核心问题原因
你当前的问题根源是每帧都会基于实时的角色局部朝向重新计算空中移动速度:你在代码中每帧都调用transform.TransformDirection(airDirectionalSpeed)将局部速度转成世界空间,当角色随视角转动后,相同的局部坐标转换出的世界坐标方向自然会跟着改变,导致空中移动方向偏移。
具体修改步骤
- 新增全局变量存储世界空间下的空中速度,在类里加一行声明:
private Vector3 worldAirVelocity;
- 修改起跳逻辑,在起跳瞬间将当前的移动方向转换为世界空间保存,修改你原来的跳跃代码段:
//JUMP or press against ground if (controller.isGrounded == true) { if (Input.GetKey(KeyCode.Space)) { currentYvel = jumpStrength; // 起跳瞬间记录当前世界空间移动速度 Vector3 currentLocalMove = new Vector3(directionalSpeed.x * directionalInput.x, 0, directionalSpeed.z * directionalInput.z); worldAirVelocity = transform.TransformDirection(currentLocalMove.normalized * Mathf.Min(currentLocalMove.magnitude, maxAirSpeed)); } else { currentYvel = -2f; } }
- 把原来的地面移动调用包到地面判断里,避免空中仍受局部输入影响:
//move player according to velocity if (Input.GetKey(KeyCode.LeftShift)) { velocity *= 1.5f; } // 仅在地面时应用局部方向的移动 if (controller.isGrounded) { controller.Move(transform.TransformDirection(velocity)); }
- 删除你原来代码里最后一段从
//set airspeed the same as character velocity开始到空中移动结束的所有逻辑,替换为下面的代码:
if (!controller.isGrounded) { // 空中仅对速度应用阻力,不重新计算方向 worldAirVelocity = Vector3.MoveTowards(worldAirVelocity, Vector3.zero, airDrag * Time.deltaTime * 100); // 直接用世界空间速度移动,不需要再做坐标转换 Vector3 airMove = worldAirVelocity * Time.deltaTime / 3; controller.Move(new Vector3(airMove.x, currentYvel * Time.deltaTime, airMove.z)); }
额外优化建议
- 你当前的WASD输入判断逻辑重复度很高,可以统一用
Input.GetAxis("Horizontal")和Input.GetAxis("Vertical")来获取输入,减少冗余代码 - 重力和移动逻辑建议放到
FixedUpdate里执行,避免不同帧率下移动速度不一致
内容的提问来源于stack exchange,提问作者MachCoyote
相关产品推荐
相关产品推荐

