- Home /
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.
What are you trying to achieve exactly? Do you want your object to reach the edge and stop, or turn around, or bounce off?
Perhaps you just need an extra bit of logic, a hasReachedEdge flag or something.
I'm also not quite sure why you're using physics (AddForce()) to move the object forward but direct control of the transform (transform.rotation=...) to change its direction. $$anonymous$$aybe a slightly different approach would avoid the issue.
What kind of approach? I am trying to make my rigidbody turn 180 degrees and walk back the direction of whence it came, and do the same thing when it reaches the other side.
Answer by clfischer · Apr 05, 2012 at 10:24 AM
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().
I do not have any new collider at the edge, so I cannot use OnTriggerEnter() (I think?) - so what kind of different check should I use? I have trouble figuring out what kind of approach to use, since all updates will cause multiple checks of the distance.
Why can't you use an extra collider? It doesn't have to be visible but it will make it easier to keep the object in the middle of your arena.
See http://answers.unity3d.com/questions/205803/bouncing-objects-and-energy-loss.html for something that sounds similar. The first part of the answer seems relevant, storing the direction of movement in a vector, detecting collisions and changing the direction using Vector3.Reflect().
Answer by clfischer · Apr 05, 2012 at 09:46 PM
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;
}
Your answer
Follow this Question
Related Questions
move player to its rotating direction? 2 Answers
Prevent Rigidbody From Rotating 3 Answers
Realistic player movement? 2 Answers
move 2d character affected by physics with velocity and/or add force 2 Answers
Rotating my character only while moving in a 2D plane 3 Answers