Unity2D点触移动平滑实现与碰撞抖动问题咨询
Hey there, let's break down your problem and fix it step by step! The core issue here is that you're directly modifying transform.position while using a dynamic Rigidbody2D—this creates a conflict between your script's forced movement and Unity's physics engine handling collisions, which causes the jitter. Let's fix this and make the movement smoother at the same time.
Why the Jitter Happens
When you use transform.position = Vector3.MoveTowards(...) in Update, you're bypassing Unity's 2D physics system. Your Rigidbody2D (set to Dynamic) is being pushed back by collisions in FixedUpdate, but your script immediately pulls it forward again in the next frame. This back-and-forth between the physics engine and your script is what causes the jitter.
Fix 1: Use Rigidbody2D for Movement (Eliminate Jitter)
Instead of modifying the transform directly, use Unity's physics-friendly methods to move your player. Here's a revised version of your script that plays nice with collisions:
using UnityEngine; public class PlayerControls : MonoBehaviour { public float speed = 5f; private Vector3 target; private Rigidbody2D rb; // Optional: For SmoothDamp (see below) private Vector3 velocity = Vector3.zero; void Start() { target = transform.position; rb = GetComponent<Rigidbody2D>(); } void Update() { // Handle input in Update (input is frame-dependent) if (Input.GetMouseButtonDown(0)) { target = Camera.main.ScreenToWorldPoint(Input.mousePosition); target.z = transform.position.z; // Keep player on the same Z-plane } } void FixedUpdate() { // All physics-related movement goes in FixedUpdate float distanceToTarget = Vector3.Distance(transform.position, target); // Only move if we're far enough from the target to avoid tiny jitters if (distanceToTarget > 0.1f) { // Option 1: Simple, consistent speed movement Vector3 newPosition = Vector3.MoveTowards(transform.position, target, speed * Time.fixedDeltaTime); rb.MovePosition(newPosition); // Option 2: Smoother acceleration/deceleration (uncomment to use) // Vector3 smoothedPosition = Vector3.SmoothDamp(transform.position, target, ref velocity, 0.1f); // rb.MovePosition(smoothedPosition); } else { // Stop the player once we reach the target rb.velocity = Vector2.zero; } } }
Key Changes Explained:
Rigidbody2D.MovePosition: This method tells Unity's physics engine to move the object, so collisions are handled naturally without conflicts.- Input in
Update, Movement inFixedUpdate: Input should be checked every frame, but physics operations need to run at a fixed timestep to stay consistent. - Distance Threshold: The
0.1fcheck prevents the player from jittering right on top of the target position by stopping movement once we're close enough. SmoothDampOption: If you want even smoother movement with natural slowdown near the target, uncomment theSmoothDamplines—it creates a more polished, organic feel.
Fix 2: Adjust Rigidbody2D Settings
Your current Rigidbody2D settings are contributing to the jitter too. Tweak these in the Inspector:
- Mass: Don't set it to
0.0001—this makes the physics behavior unstable. Use a reasonable value like1(adjust based on your game's scale). - Linear Drag: Set this to
1or2—it adds resistance to movement, making the player stop smoothly instead of sliding. - Angular Drag: Set to
5or higher to prevent unwanted rotation if your player hits obstacles. - Collision Detection: Keep it on
Continuous—this helps prevent the player from passing through thin colliders at high speeds.
Quick Recap
- Never modify
transform.positiondirectly when using a dynamic Rigidbody—userb.MovePositioninstead. - Split input handling and physics movement into
UpdateandFixedUpdaterespectively. - Add a small distance threshold to avoid jitter at the target position.
- Fix your Rigidbody2D settings to avoid unstable physics behavior.
This should give you smooth, collision-friendly point-and-click movement without any jitter!
内容的提问来源于stack exchange,提问作者user12793596

