Unity 2D角色触碰墙体抖动问题求助(附PlayerMovement代码)
2D角色碰墙抖动的原因与修复方案
问题原因
- 直接修改Transform与物理引擎冲突:你在
Update里用transform.position += ...直接改变角色位置,但角色的Rigidbody2D会由物理引擎在FixedUpdate阶段处理碰撞和位置修正。当角色撞墙时,物理引擎会把角色从墙体推开,而你的代码又强行把角色往墙的方向挪,两者反复拉扯就造成了画面抖动。 - 物理逻辑与更新时机不匹配:
Update的帧率不固定,而物理更新是固定间隔的FixedUpdate,在Update里处理物理相关的移动,会导致和物理引擎的计算不同步,进一步加重抖动。
修复方案
核心思路是让物理引擎全权负责角色的位置计算,不要直接修改transform.position,同时把物理相关逻辑移到FixedUpdate中:
修改后的完整代码
using UnityEngine; public class PlayerMovement : MonoBehaviour { public float MovementSpeed = 5f; public float JumpForce = 7f; private Rigidbody2D _rigidbody; private float coyoteTime = 0.2f; private float coyoteTimeCounter; private float jumpBufferTime = 0.05f; private float jumpBufferCounter; [SerializeField] private Transform groundCheck; [SerializeField] private LayerMask groundLayer; private bool isGrounded() { return Physics2D.OverlapCircle(groundCheck.position, 0.2f, groundLayer); } private void Start() { // 统一获取刚体组件,移除冗余字段 _rigidbody = GetComponent<Rigidbody2D>(); } private void Update() { // 仅处理输入检测、状态计时等非物理逻辑 if (isGrounded()) { coyoteTimeCounter = coyoteTime; } else { coyoteTimeCounter -= Time.deltaTime; } if (Input.GetButtonDown("Jump")) { jumpBufferCounter = jumpBufferTime; } else { jumpBufferCounter -= Time.deltaTime; } // 跳跃松开逻辑放在Update,保证输入检测及时 if (Input.GetButtonUp("Jump") && _rigidbody.velocity.y > 0f) { _rigidbody.velocity = new Vector2(_rigidbody.velocity.x, _rigidbody.velocity.y * 0.5f); coyoteTimeCounter = 0f; } } private void FixedUpdate() { // 所有物理相关操作放在FixedUpdate,和物理引擎同步 var movement = Input.GetAxis("Horizontal"); // 通过修改刚体速度控制水平移动,交给物理引擎处理碰撞 _rigidbody.velocity = new Vector2(movement * MovementSpeed, _rigidbody.velocity.y); // 跳跃的物理操作同步移到此处 if (coyoteTimeCounter > 0f && jumpBufferCounter > 0f) { _rigidbody.velocity = new Vector2(_rigidbody.velocity.x, JumpForce); jumpBufferCounter = 0f; } } }
关键改动说明
- 移除直接修改transform的代码:用
_rigidbody.velocity控制水平移动,让物理引擎统一处理碰撞后的位置修正,彻底避免代码强制移动和物理修正的拉扯冲突。 - 拆分逻辑到对应生命周期:
Update处理输入、状态计时,FixedUpdate处理所有刚体物理操作,保证和物理引擎的更新频率完全同步。 - 清理冗余代码:删除重复声明的
rigidbody2D字段,统一使用_rigidbody获取组件,避免代码混淆。
内容的提问来源于stack exchange,提问作者Tyler Bryant
相关产品推荐
相关产品推荐

