Unity2D平台游戏角色贴墙粘滞问题求助:如何解决该移动异常?
Hey there! That wall-sticking issue is super common when starting out with 2D platformers—let's break down what's causing it and how to fix it, covering both your code and Unity settings.
First, Why Is This Happening?
Your current code directly sets the Rigidbody2D's velocity to a fixed value when holding movement keys. When your character presses against a wall, Unity's physics engine tries to push the character away to resolve the collision, but your code immediately overrides the velocity right back. This constant "tug-of-war" between the physics engine and your input logic creates that sticky feeling. On top of that, your collision-based jump logic triggers on all collisions (including walls), which adds unexpected behavior too.
Step 1: Fix Your Movement Code
Let's rewrite the movement to work with Unity's physics instead of fighting against it. Here's how to adjust your PlayerController script:
1. Update Movement Logic (Stop Directly Setting Velocity)
Instead of hard-setting velocity to ±moveSpeed, use smooth acceleration and let the physics engine handle collisions naturally. Replace your HorMoveKeyDown method with this:
private void HorMoveKeyDown() { // Get raw input for snappier keyboard controls float moveInput = Input.GetKey("d") ? 1f : Input.GetKey("a") ? -1f : 0f; // Calculate target velocity and smooth transition to it float targetVelocityX = moveInput * moveSpeed; float smoothVelocityX = Mathf.MoveTowards(myRigBody.velocity.x, targetVelocityX, 10f * Time.deltaTime); myRigBody.velocity = new Vector2(smoothVelocityX, myRigBody.velocity.y); }
This way, if the physics engine modifies the X velocity (like when hitting a wall), your code will gradually adjust instead of forcing it back instantly.
2. Fix Jump Collision Logic
Your current OnCollisionEnter2D and OnCollisionExit2D reset jumps on any collision (including walls), which is not what you want. Instead, use a ground check to detect when you're actually on the ground:
- Add a small empty GameObject as a child of your player, placed just below their feet (name it
GroundCheck). - Update your script with these changes:
// Add these serialized fields at the top [SerializeField] private Transform groundCheck; [SerializeField] private LayerMask groundLayer; private bool isGrounded; void Update() { // Check if the ground check overlaps with the ground layer isGrounded = Physics2D.OverlapCircle(groundCheck.position, 0.1f, groundLayer); // Reset jumps only when grounded if (isGrounded) { jumpsAvailable = maxJumps; } // Update joystick movement to use smooth velocity too if (usingJoystick) { moveInput = Input.GetAxis("Horizontal"); float targetVelocityX = moveInput * moveSpeed; float smoothVelocityX = Mathf.MoveTowards(myRigBody.velocity.x, targetVelocityX, 10f * Time.deltaTime); myRigBody.velocity = new Vector2(smoothVelocityX, myRigBody.velocity.y); } else { HorMoveKeyDown(); JumpKeyDown(); } HorDrag(); } // Remove the old OnCollisionEnter2D and OnCollisionExit2D methods entirely
Make sure to set the groundLayer in the Inspector to the layer you're using for ground objects (don't include walls here!).
3. Tweak Horizontal Drag
Your HorDrag method can stay, but using Mathf.MoveTowards makes it smoother and more consistent:
private void HorDrag() { if (!(Input.GetKey("a") || Input.GetKey("d"))) { myRigBody.velocity = new Vector2(Mathf.MoveTowards(myRigBody.velocity.x, 0f, xDrag * Time.deltaTime), myRigBody.velocity.y); } }
Step 2: Adjust Unity Editor Settings
Even with fixed code, physics materials can cause sticking. Let's fix that:
- Add Physics Material 2D: Create a new
Physics Material 2D(right-click in Project window → Physics 2D → Physics Material 2D). Set its Friction to0and Bounciness to0. Assign this material to both your player's Collider2D and your wall Collider2Ds to eliminate friction-based sticking. - Rigidbody2D Settings: Select your player's Rigidbody2D:
- Set Collision Detection to
Continuous(prevents collision glitches at higher speeds). - Check Freeze Rotation Z (so your player doesn't spin when hitting walls).
- Ensure Gravity Scale is set to a reasonable value (like
3or4—too high can cause weird collision behavior).
- Set Collision Detection to
Final Notes
Test these changes step by step—start with the code fixes, then adjust the physics materials if you still see sticking. Platformer movement is all about balancing smooth input with natural physics, so don't hesitate to tweak the acceleration or drag values until it feels right for your game!
内容的提问来源于stack exchange,提问作者ShapesGameDev

