低帧率下Rigidbody2D角色跳跃过高的问题修复咨询
低帧率下跳跃过高问题修复方案
问题根源
你的跳跃逻辑用帧计数(_jumpTime)控制持续跳跃的时长,低帧率时每帧的时间间隔大幅变长(比如5FPS下每帧0.2秒,60FPS下仅0.016秒),同样的_maxJumpTime=40,实际持续的物理时间会从正常的~0.67秒变成8秒——相当于持续给角色施加向上速度的时间被强行拉长,自然跳得极高。
修复步骤
- 把帧计数改成时间计数:用基于秒的时长替代帧数量,确保不管帧率高低,跳跃持续的物理时间一致。
- 将物理相关逻辑移到FixedUpdate:FixedUpdate的调用间隔是固定的(默认0.02秒),不受帧率波动影响,物理操作在这里执行更稳定。
- 分离输入与物理逻辑: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
相关产品推荐
相关产品推荐

