Update speed and physics makes my rigidbody jiggle

Hi.

I have a Rigidbody with collider moving across a small flat area:

void FixedUpdate () {
	rigidbody.AddForce(transform.forward * 5);
(...)

I have a function that detects how close to the edge the object is. Basically just a straight down raycast that looks at the distance between my Rigidbody and the RaycastHit.collider.bounds.center variable.

So my problem is, that when my character gets close to the edge, I check if the distance is over 1.0f:

if(distance_to_center > 1.0f) {
	float new_rotation = Mathf.Ceil(transform.eulerAngles.y + 180.0f);
	transform.rotation = Quaternion.Euler(0, new_rotation, 0);
}

My problem is now, that FixedUpdate() updates too fast compared to the velocity of my Rigidbody. So one update goes by, and my conditions is fulfilled, the Rigidbody turns 180 degrees and starts moving the other direction. Then another updates arrives, and notices that my character has not yet had time to move out of the way, and then updates it again to go the other way.

Resulting in my rigidbody just going into spasm and moves back and forward constantly.

What do I do to avoid this? I have had this issue with quite many things.

Thanks.

Your condition needs to be checked differently. The distance_to_center can be greater than 1.0 for several timesteps. At each of these timesteps you rotate the object 180 degrees, so the behaviour you’re observing is expected.

Instead you need to use a function that is only going to be called once. Perhaps put your rotation code in OnTriggerEnter() or OnColliderHit(). Or instead of rotating the object directly, apply a force so it bounces off the edge and then rotate it so it is facing in the direction of movement.

You also don’t need to use Mathf.Ceil().

Here’s another idea. Give your condition some hysteresis. In the following snippet, when you reach the edge the first time, you turn around and a flag is set to indicate that you have just turned around. This flag prevents turning again. It is reset only when you get close to the center again. The same sequence happens again when you reach the other side.

bool just_turned = false;
if (distance_from_center > 1.0f && !just_turned) {
	turn_around();
	just_turned = true;
}
if (distance_from_center < 0.5f) {
	just_turned = false;
}