Proper Way to Constrain Rigidbody


I want to be able to constrain my rigidbody within a given range. I understand there is already a constrain system on the Rigidbody behaviour, but this locks it from the already given position.

I want to have mine within a range, so if rigidbody.position falls below 2, then lock it at 2. And if it jumps higher than 5, then lock it at 5, but with gravity.

I suppose I could do something like this:

if(rigidbody.position.y > 5){
	//gravity will take affect, and will begin to fall - thats fine
	rigidbody.position.y = 5;

if(rigidbody.position.y < 2){
	rigidbody.position.y = 2;

Is this the correct way to do something like this? Will this cause any physics glitches? I remember a while back I tried sticking my player on a fixed Y axis in a similar way, and it messed with the collision - and cause the player to sometimes walk through walls by pressing and ‘rubbing’ against colliders.

If possible, invisible colliders are better (maybe on a layer only that object can hit.) But that can’t always be done. Clamping in code, like your example, can give fine results, but is always fighting physics a little. Some comments:

Leave some slack. A real physics constraint would go “move, auto-clamp to 5, check for hits,” so could never hit anything at 5.01. With code-clamping, the object gets one move past 5, so can.

Untested: maybe try rigidbody.MovePosition. It “talks” to the other objects as it moves (see next para.)

Yes, also set Y-velocity to 0 after a clamp (or times -1?) Otherwise object1 will move to 5.01 each frame, leaving a little fake space below it. Object2 can move there. Then your code snaps down object1. Then physics see they’re mysteriously overlapping, and blasts object2 away.

Maybe put the code in FixedUpdate. Physics moves during physics steps, which are sprinkled in-between normal Updates. You might get 2 or 3 physics moves before an Update runs to clamp the value.

position-dot-y: yes, C# has a design flaw that you aren’t allowed to change parts of many fields – only all at once. So Vector3 A; A.y=5; is legal. But thing.A.x=5; often isn’t. You get to write Vector3 pos=transform.position; pos.y=5; transform.position=pos;.