You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
    }
}

关键修改说明

  1. 修复重复乘Time.deltaTime问题:将垂直方向的位移计算改为直接赋值move.y = yVelocity,仅在调用characterController.Move时统一乘以一次Time.deltaTime,确保所有方向的位移计算逻辑一致,彻底消除帧率依赖。
  2. 用物理公式计算跳跃初速度:通过公式v = sqrt(2 * |g| * h)计算跳跃初速度,让跳跃高度稳定可控,jumpHeight改为直观的米数(比如2代表跳2米),数值更易调整。
  3. 优化地面状态逻辑:只要在地面就直接重置yVelocity为0,确保落地后重力计算从零开始;改用Input.GetKeyDown触发跳跃,避免按住空格持续跳跃的问题。
  4. 修正视角旋转错误:移除原代码中相机固定的y轴旋转值10,让视角旋转正常跟随鼠标操作。

内容的提问来源于stack exchange,提问作者TotalUmbrella

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 13:10:35