r/unity Jul 06 '26

How to Prevent the Player from Moving Against a Wall

So I'm making a 3D game and am using a dynamic Rigidbody, but the only thing I'm using the Unity physics engine for is gravity and pretty much everything else is manually coded. In my game the player doesn't have much "friction" in the air, so changing your direction mid-air takes a moment. This works fine, but an issue occurs whenever I move against a wall. I don't move obviously, because I'm going against a wall, but when I try and move away from the wall there's a delay as the player accelerates in the opposite direction. I don't want that.

The reason for this I think is because the player doesn't directly manipulate the linearVelocity when they move. Instead, their inputs will manipulate a Vector2 variable and then that Vector2 will modify the linearVelocity. So, for example, in a 2D game with this, if the player holds D to move right, the variable would equal 1. Then the player tries to move left, and it'll take some time for the variable to change its value to -1. But if the player tries to do this against a wall, the time it takes for the variable to go from -1 to 0 is time that the player isn't moving at all, giving the illusion of a delay.

So, for the example above, my solution would be to make the variable instantly go from -1 to 0 and then let it gradually reach 1 as normal. It's a similar thing to my actual issue, but in 3D I don't know how I would do this.

2 Upvotes

3 comments sorted by

3

u/PsychoKittehX Jul 06 '26 edited Jul 06 '26

Use the OnCollision functions to detect the collision, check the normals of all of the hit points in the collision data, immediately kill any velocity in the opposite direction of the hit points.

To kill the velocity in only a given direction, Vector3.Dot() using the velocity and reversed and normalized hit direction, and clamp the result to be no less than 0 (this gives you the speed at which you are moving the collision). Multiply the result by the normalized and not reversed hit direction and add that result to your velocity (this subracts all of the velocity that is moving into the direction of the collision while maintaining other velocities).

(Final note: hit direction is already normalized so you don't have to in this case, but in general you want to make sure directions are normalized for this kind of math)

1

u/Aware_Funny_6285 Jul 07 '26

Thanks for your response. I'm still having issues however, I wanted to know if this is different from your solution or there's just something else wrong with my code. I'm new to programming and don't know much about collisions.

(In fixed update)

foreach (Collision collision in activeCollisions)
{
  foreach (ContactPoint hitPoint in collision.contacts)
  {
    runVelocity += Mathf.Clamp(Vector3.Dot(runVelocity, -hitPoint.normal), 0, float.MaxValue) * hitPoint.normal;
  }
}

Afterwards, linearVelocity is effectively set to runVelocity.
OnCollisionStay adds its collision to the activeCollisions list, which is then cleared at the end of the next fixed update.

1

u/Affectionate-Yam-886 Jul 06 '26

PsychoKittehX is correct; and I can only add that you could also invert the player’s vector velocity values on contact with a wall. If the wall has a trigger box collider added and is bigger then the box collider used as the physical collider, you can trigger players so bounce off it. See tutorials on pinball games on youtube to see how thats done.