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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:30:51