- Home /
Continously correct rotation
I'm trying to continously correct the rotation of an object. Imagine a spaceship. When the spaceship collides on a side it rotates and then automatically rotates again to be "flat" again.
I tried things like this
function Update(){
var newRotation = Quaternion.AngleAxis(0, Vector3.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, newRotation, Time.deltaTime * 2.0f * 10);
}
and the same using Slerp.
For both the object starts jittering fast.
How can archieve this correction over time smoothly? Should I change the approach? I'm doing something wrong in the current code?
Any suggestion is welcome
Thank you.
A few things you might try:
Try putting your code in LateUpdate ins$$anonymous$$d of Update.
Use Quaternion Lerp/Slerp ins$$anonymous$$d of RotateTowards
Both 1 and 2.
Is the spaceship moving using rigidbodies/physics?
If so, hand-turning (outside of physics) can push it through an object, giving some ugly jitter/bounce/snap depending. Have to set angularVelocity, and let physics do the spinning. Works, but is a huge pain to do the math.
Hi, first of all thanks for the answers.
sevensixtwo, I tried those points:
It gave me the same effect on both Update and LateUpdate. Then I updated Unity and the shake almost went off in LateUpdate. But it didn't behave as expected so I think the problem is in the approach rather than the code.
With Lerp/Slerp the jittering came back
LateUpdate didn't help with Lerp/Slerp
OwenReynolds, I understand but the object jitters after a collission and not collisioning (in the air, without gravity). Anyway, I tried another approach using forces once some rotation threshold is reached, it "works" but the result is not quite good.
The object starts dumping one side to the other.
Here's the code:
if(transform.rotation.eulerAngles.z > 0+rotationThreshold && transform.rotation.eulerAngles.z < 180)
rigidbody.AddRelativeTorque(-transform.forward * autoBalanceForce * transform.rotation.eulerAngles.z);
if(transform.rotation.eulerAngles.z >= 180 && transform.rotation.eulerAngles.z < 359-rotationThreshold)
rigidbody.AddRelativeTorque(transform.forward * autoBalanceForce * -(transform.rotation.eulerAngles.z-360));
if(transform.rotation.eulerAngles.y > 0+rotationThreshold && transform.rotation.eulerAngles.y < 180)
rigidbody.AddRelativeTorque(-transform.up *autoBalanceForce * transform.rotation.eulerAngles.y);
if(transform.rotation.eulerAngles.y >= 180 && transform.rotation.eulerAngles.y < 359-rotationThreshold)
rigidbody.AddRelativeTorque(transform.up * autoBalanceForce * -(transform.rotation.eulerAngles.y-360));
if(transform.rotation.eulerAngles.x > 0+rotationThreshold && transform.rotation.eulerAngles.x < 180)
rigidbody.AddRelativeTorque(-transform.right * autoBalanceForce * transform.rotation.eulerAngles.x);
if(transform.rotation.eulerAngles.x >= 180 && transform.rotation.eulerAngles.x < 359-rotationThreshold)
rigidbody.AddRelativeTorque(transform.right * autoBalanceForce * -(transform.rotation.eulerAngles.x-360));
I'm not very happy with the "forces" approach because I have no guarantee that the object will end up in the correct position. Or that it won't go spinning wild under certain conditions.
Any ideas on how to get that in a different way? Anyway thank you for your suggestions, they were useful
Answer by drudiverse · Oct 01, 2014 at 08:34 PM
If you are using physics, you can try relative torque towards the flat angle, similar to how a pilot would use side thrusters to stabilise. i.e. complex mix of non linear relative torque levels relative to rotation angle, and some if conditions.
to get rid of jitter, you should switch off the physics at any time that you are rotating manually the rotation variables... do that by changing the rotation velocity http://docs.unity3d.com/ScriptReference/Rigidbody-angularVelocity.html
you can change it slowly relative to time, and you can change the drag coefficient too while stabilising if it makes the craft more responsive, it can be like invisible thrusters increasing drag.
float dot = Vector3.Dot(transform.right, Vector3.down);
rigidbody.AddRelativeTorque(Vector3.forward*dot*100*Time.deltaTime);
sometimes fixedupdate and lateupdate can make different to jitter, i just fixed a jitter prob using FixedUpdate.
Answer by hlynbech · Oct 01, 2014 at 08:31 PM
If it is the physics engine that gives the jittering, you could temporarily disable the physics (fx Rigidbody or BoxCollider or whatever) component on your object, just while you make the animation as originally posted.
And then reenable those same components when all is back in place, and the game continues.
Code examples on enable/disable: http://answers.unity3d.com/questions/26844/enabledisable-specific-components.html
Answer by AsLoGD · Oct 02, 2014 at 12:42 AM
Thanks for the answers. I can't upvote for having little reputation.
Disabling the physics is not an option because I need to always detect collisions. At the end I'm using physics and creating torque to the object under some conditions.
Here's some code:
if(transform.rotation.eulerAngles.z > 0+rotationThreshold && transform.rotation.eulerAngles.z < 180)
rigidbody.AddRelativeTorque(-transform.forward * autoBalanceForce * transform.rotation.eulerAngles.z);
if(transform.rotation.eulerAngles.z >= 180 && transform.rotation.eulerAngles.z < 359-rotationThreshold)
rigidbody.AddRelativeTorque(transform.forward * autoBalanceForce * -(transform.rotation.eulerAngles.z-360));
I'm doing this for every axis.
It REALLY helped increasing the angular drag of the rigidbody, so it stops bouncing side to side in little time.
I think I can consider this as resolved. Do I have to do anything in special?
See you around
With this "physics push" approach, the final touch, for me, was avoiding the "waggle" around the final position. Did that by dropping the push and damping the force, once I got very close (you may be doing that with auto-balance force?) Then adding a hacky "if you're super close, really clamp down the speed."
Have to be a little careful, since you still want a big force to be able to spin you out of line.
For push math, exa$$anonymous$$ing each rotationAngle doesn't always work. They sometimes snap by +/-180, like going from 2:44pm to "quarter til 3." Not a Unity thing, just a fact of rotation math. But if it's working so far, keep it!!!
What worked for me, and drudverse is sort-of doing this, is to push around an axis. It turns out the correct push axis is the cross product of the way you want to face, and the current facing. Bizzarely, if you add a multiple of that to angularVelocity, it pushes the correct way.
Your answer
Follow this Question
Related Questions
Jitter on Slerp - Raycast 0 Answers
Slerp / lerp not creating a smooth transition 2 Answers
HoloLens - Smooth Rotation doesn't work 0 Answers
Smooth rotation problem 1 Answer
Filter rotation without Slerp 1 Answer