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

低帧率下Rigidbody2D角色跳跃过高的问题修复咨询

低帧率下跳跃过高问题修复方案

问题根源

你的跳跃逻辑用帧计数(_jumpTime)控制持续跳跃的时长,低帧率时每帧的时间间隔大幅变长(比如5FPS下每帧0.2秒,60FPS下仅0.016秒),同样的_maxJumpTime=40,实际持续的物理时间会从正常的~0.67秒变成8秒——相当于持续给角色施加向上速度的时间被强行拉长,自然跳得极高。

修复步骤

  1. 把帧计数改成时间计数:用基于秒的时长替代帧数量,确保不管帧率高低,跳跃持续的物理时间一致。
  2. 将物理相关逻辑移到FixedUpdate:FixedUpdate的调用间隔是固定的(默认0.02秒),不受帧率波动影响,物理操作在这里执行更稳定。
  3. 分离输入与物理逻辑:Update只处理输入状态判断,把实际的物理操作交给FixedUpdate,避免帧率波动干扰物理计算。

修改后的代码示例

using UnityEngine.InputSystem;
using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
public class PlayerMove : MonoBehaviour
{
    private PlayerMovement _playerMovement;
    private Rigidbody2D _rb;
    
    [SerializeField] private LayerMask groundLayer;

    [SerializeField] private float speed = 5.0f;
    [SerializeField] private float jumpHeight = 8.0f;
    // 改成基于秒的跳跃持续时长,比如0.2秒,可根据手感调整
    [SerializeField] private float maxJumpDuration = 0.2f;

    private bool _isJumping;
    private float _currentJumpTimer;

    private void Awake() {
        _playerMovement = new PlayerMovement();
    }

    private void Start() {
        _rb = GetComponent<Rigidbody2D>();
    }

    private void OnEnable() {
        _playerMovement.Enable();
    }

    private void OnDisable() {
        _playerMovement.Disable();
        _playerMovement.Dispose();
    }

    private bool isGrounded() => Physics2D.Raycast(transform.position, Vector3.down, 0.6f, groundLayer) 
                              || Physics2D.Raycast(new Vector2(transform.position.x - 0.5f, transform.position.y), Vector3.down, 0.6f, groundLayer) 
                              || Physics2D.Raycast(new Vector2(transform.position.x + 0.5f, transform.position.y), Vector3.down, 0.6f, groundLayer);

    private void Update() {
        // 仅处理输入状态,不碰物理逻辑
        if(_playerMovement.Movement.Jumping.WasPerformedThisFrame() && isGrounded())
        {
            _isJumping = true;
            _currentJumpTimer = maxJumpDuration;
        }

        if (_playerMovement.Movement.Jumping.WasReleasedThisFrame()) 
        {
            _isJumping = false;
        }

        if (isGrounded()) 
        {
            _currentJumpTimer = maxJumpDuration;
            if (!_playerMovement.Movement.Jumping.IsPressed())
                _isJumping = false;
        }
    }

    private void FixedUpdate() {
        // 移动逻辑保持不变
        Vector2 inp = _playerMovement.Movement.Move.ReadValue<Vector2>();
        _rb.velocity = new Vector2(inp.x * speed , _rb.velocity.y);

        // 跳跃逻辑移到FixedUpdate,用固定时间步长更新计时器
        if(_playerMovement.Movement.Jumping.IsPressed() && _isJumping && _currentJumpTimer > 0)
        {
            _rb.velocity = new Vector2(_rb.velocity.x, jumpHeight);
            // 用fixedDeltaTime确保时间计算不受帧率影响
            _currentJumpTimer -= Time.fixedDeltaTime;
        }
        else if (_currentJumpTimer <= 0)
        {
            _isJumping = false;
        }
    }
}

额外优化建议

  • 给Rigidbody2D开启Interpolate选项,让低帧率下角色移动更平滑;
  • 地面检测可以改用Physics2D.OverlapBox替代多道射线,性能和稳定性更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 21:01:36