Unity Character Controller无法跳跃且移动时isGrounded误判问题求助
问题原因及修复方案
1. isGrounded移动时返回false的原因
- CharacterController的
isGrounded属性仅在调用Move方法后更新,且需要角色持续有向下的微小压力贴合地面,才会返回正确值 - 原有代码存在两个核心错误:
- 多次调用
controller.Move,导致isGrounded状态更新混乱 - 处理水平移动时直接覆盖整个
moveDir变量,清空了之前的y轴重力数值,移动时角色失去向下的贴地压力,触发悬空判定
- 多次调用
2. 跳跃无响应的原因
- 跳跃判定写在重力判定逻辑之后,且本身
isGrounded判定错误,几乎不会触发跳跃分支 - 即使触发跳跃,下一帧处理水平移动时会直接清空
moveDir的y轴数值,跳跃速度直接失效
修正后代码
public Transform cam; public float speed = 6f, turnSmoothTime = 0.1f, jumpSpeed = 10f, gravity = -9.81f; float turnSmoothVelocity; Vector3 moveDir; void Update() { // 保留上一帧的y轴速度,不要直接清空 float horizontal = Input.GetAxisRaw("Horizontal"); float vertical = Input.GetAxisRaw("Vertical"); Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized; // 处理水平移动,仅修改x、z轴数值 if (direction.magnitude >= 0.1f) { float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y; float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime); transform.rotation = Quaternion.Euler(0f, angle, 0f); Vector3 horizontalMove = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward; moveDir.x = horizontalMove.normalized.x * speed; moveDir.z = horizontalMove.normalized.z * speed; } else { // 无水平输入时清空x、z速度 moveDir.x = 0; moveDir.z = 0; } // 优先处理跳跃和接地判定 if (controller.isGrounded) { // 接地时给一个微小的向下速度,保证贴地检测正常 moveDir.y = -2f; if (Input.GetButtonDown("Jump")) { moveDir.y = jumpSpeed; Debug.Log("Jump"); } } // 统一应用重力 moveDir.y += gravity * Time.deltaTime; // 单帧内仅调用一次Move方法,避免状态更新异常 controller.Move(moveDir * Time.deltaTime); }
额外注意点
- 不要多次调用
controller.Move,单帧内多次调用会导致碰撞和接地状态计算异常 - CharacterController不会自动应用重力,必须手动持续累加重力数值,才能保证
isGrounded判定正常
内容的提问来源于stack exchange,提问作者skirsch00
相关产品推荐
相关产品推荐

