Unity CharacterController跳跃时无法保持水平移动问题求助
问题原因
你代码中moveDirection *= moveSpeed的逻辑被包裹在if(isGrounded)判断分支内,角色离开地面后该逻辑不再执行,moveDirection仅保留输入轴返回的-1到1的原始数值,没有乘以实际移动速度,所以表现为跳跃时水平移动中断、原地起跳。
修复方案
- 调整逻辑执行顺序:先判断行走/奔跑状态完成
moveSpeed赋值,再给moveDirection乘以移动速度 - 将
moveDirection *= moveSpeed移出if(isGrounded)判断块,保证空中也能正常计算水平移动速度
修正后完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Movementcontroller : MonoBehaviour { //VARIABLES [SerializeField] private float moveSpeed; [SerializeField] private float walkSpeed; [SerializeField] private float runSpeed; private Vector3 moveDirection; private Vector3 velocity; [SerializeField] private bool isGrounded; [SerializeField] private float groundCheckDistance; [SerializeField] private LayerMask groundMask; [SerializeField] private float gravity; [SerializeField] private float jumpHeight; //REFERENCES private CharacterController controller; private void Start() { controller = GetComponent<CharacterController>(); } private void Update() { Move(); } private void Move() { isGrounded = Physics.CheckSphere(transform.position, groundCheckDistance, groundMask); if(isGrounded && velocity.y < 0) { velocity.y = -2f; } float moveZ = Input.GetAxis("Vertical"); float moveX = Input.GetAxis("Horizontal"); moveDirection = new Vector3(moveX, 0, moveZ); moveDirection = transform.TransformDirection(moveDirection); // 先判断移动状态,确定moveSpeed数值 if(moveDirection != Vector3.zero && !Input.GetKey(KeyCode.LeftShift)) { Walk(); } else if(moveDirection != Vector3.zero && Input.GetKey(KeyCode.LeftShift)) { Run(); } else if(moveDirection == Vector3.zero) { Idle(); } // 移动速度赋值放到isGrounded判断外,空中也生效 moveDirection *= moveSpeed; if(isGrounded) { if(Input.GetKeyDown(KeyCode.Space)) { Jump(); } } controller.Move(moveDirection * Time.deltaTime); velocity.y += gravity * Time.deltaTime; controller.Move(velocity * Time.deltaTime); } private void Idle() { } private void Walk() { moveSpeed = walkSpeed; } private void Run() { moveSpeed = runSpeed; } private void Jump() { velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity); } }
可选优化
如果需要区分地面和空中的移动灵敏度,可以额外定义一个[SerializeField] private float airControlRate = 0.8f;的系数,在空中时给moveDirection额外乘以该系数,即可实现更符合直觉的空中阻尼效果。
内容的提问来源于stack exchange,提问作者Nexet
相关产品推荐
相关产品推荐

