Unity角色控制器跳跃高度与重力受帧率影响问题求助
解决Unity角色控制器帧率相关的跳跃/重力异常问题
问题根源
- 重复乘以Time.deltaTime:代码中
move = move + Vector3.up * yvelocity * Time.deltaTime已经计算了垂直方向的位移,之后又执行characterController.Move(move * Time.deltaTime),导致垂直位移被两次乘以时间增量。帧率越高,Time.deltaTime越小,两次相乘后垂直方向的累积错误会让重力效果被削弱、跳跃高度被放大。 - 跳跃初速度设置不合理:直接给
jumpHeight设为550这种超大值,不符合物理逻辑,也会放大帧率带来的误差。 - 地面状态下速度重置不严谨:仅在
yvelocity <= 0时才重置为0,可能导致落地时速度没有及时清零,影响后续重力计算。
修正后的代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Movement : MonoBehaviour { public float speed = 10f; private CharacterController characterController; private float sensitivity = 1.8f; private float xRotation = 0f; public Camera camera; // 改为设置期望的跳跃高度(单位:米),而非直接给初速度 public float jumpHeight = 2f; private float gravity = -9.81f * 2f; // 用接近现实的重力值,乘以2增强游戏手感 private float yVelocity = 0f; private bool landed = false; public AudioSource landSound; void Start() { characterController = GetComponent<CharacterController>(); Cursor.lockState = CursorLockMode.Locked; } void Update() { // 鼠标视角控制 float mouseX = Input.GetAxis("Mouse X") * sensitivity; float mouseY = Input.GetAxis("Mouse Y") * sensitivity; xRotation -= mouseY; xRotation = Mathf.Clamp(xRotation, -90f, 90f); camera.transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f); // 修复原代码中固定的y轴旋转偏移 transform.Rotate(Vector3.up * mouseX); // 移动速度切换 speed = Input.GetKey(KeyCode.LeftShift) ? 15f : 10f; // 水平方向移动计算 Vector3 forward = transform.TransformDirection(Vector3.forward); Vector3 right = transform.TransformDirection(Vector3.right); Vector3 move = (forward * Input.GetAxis("Vertical") + right * Input.GetAxis("Horizontal")) * speed; // 跳跃与重力处理 if (characterController.isGrounded) { // 落地时强制重置垂直速度 yVelocity = 0f; // 用物理公式计算跳跃初速度:v = sqrt(2 * |重力| * 跳跃高度) if (Input.GetKeyDown(KeyCode.Space)) // 改用GetKeyDown避免按住空格持续触发跳跃 { yVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity); } // 播放落地音效 if (!landed) { landSound?.Play(); landed = true; } } else { landed = false; } // 更新垂直速度 yVelocity += gravity * Time.deltaTime; // 将垂直速度直接赋值给移动向量的y分量 move.y = yVelocity; // 统一执行移动:仅在最后乘以一次Time.deltaTime characterController.Move(move * Time.deltaTime); } }
关键修改说明
- 修复重复乘Time.deltaTime问题:将垂直方向的位移计算改为直接赋值
move.y = yVelocity,仅在调用characterController.Move时统一乘以一次Time.deltaTime,确保所有方向的位移计算逻辑一致,彻底消除帧率依赖。 - 用物理公式计算跳跃初速度:通过公式
v = sqrt(2 * |g| * h)计算跳跃初速度,让跳跃高度稳定可控,jumpHeight改为直观的米数(比如2代表跳2米),数值更易调整。 - 优化地面状态逻辑:只要在地面就直接重置
yVelocity为0,确保落地后重力计算从零开始;改用Input.GetKeyDown触发跳跃,避免按住空格持续跳跃的问题。 - 修正视角旋转错误:移除原代码中相机固定的y轴旋转值10,让视角旋转正常跟随鼠标操作。
内容的提问来源于stack exchange,提问作者TotalUmbrella
相关产品推荐
相关产品推荐

