x


Rotate using physics

I've seen a question like this posted several times, but never answered properly.

I want to rotate an object to a specific rotation using the physics engine. All of the answers I've seen said to just slerp the angle, but I don't want to do that because if the object collides with another and acquires rotational velocity, it should be thrown off by that rotation. Slerping the angle would prevent any of those collision physics from affecting anything.

Its a spaceship game, and I want the objects to have to apply acceleration and deceleration forces, and have to fight rotation gained from collisions to reach specified angles, so using slerp is unacceptable. If all you have to say is "don't use physics, use slerp," please don't bother

more ▼

asked Apr 06 '12 at 04:14 AM

Zachary.C.Stewart gravatar image

Zachary.C.Stewart
31 1 1 2

I had this problem also ... and walked away. The problem is the calculations.

As you approach the target rotation, torque has to be applied in the opposite direction (to slow the rotation) , While also decreasing the torque being applied as the initial turning force.

I havn't tried using any trickery like when rotation is reached hitting it with transform.rotation or LookAt or LookRotation . Or maybe the physics-based command Rigidbody.MoveRotation or FreezeRotation or RigidbodyConstraints.FreezeRotation might work :

http://unity3d.com/support/documentation//ScriptReference/Rigidbody.MoveRotation.html

http://unity3d.com/support/documentation//ScriptReference/Rigidbody-freezeRotation.html

Apr 06 '12 at 01:41 PM alucardj
(comments are locked)
10|3000 characters needed characters left

3 answers: sort newest

Well I think that your problem is not physics, your problem is engineering. To get a precise angle the answer depends on the inertia tensor of that certain body. You would have to solve newton equation of motion for a rigid body or, in a more aerospatial spirit, tell the ship to add a torque strong enough to stop when it reaches the desired position. In any case you would need pen and paper but I bet second option is easier. I guess that real space ships would have the same problem as you do, and in fact satellites have to use gyroscopes to rotate and then they use it in the opposite way to stop (because of the small friction in space).

more ▼

answered Nov 28 '12 at 10:42 AM

MrVerdoux gravatar image

MrVerdoux
133 1 2

(comments are locked)
10|3000 characters needed characters left

Physics is not intended to allow precise positioning. To rotate a rigidbody with torque, you should write a PID controller, but feedback about the current rigidbody orientation is very unreliable (eulerAngles may return weird values, and changes from 0-360 and 360-0 when near to the origin). Take a look at this question, where I proposed an alternative physics control.

EDITED: The general idea behind a PID controller is explained in this pseudo code:

var pGain: float; // adjust the individual gains
var iGain: float; // iGain better to be 0 in this case
var dGain: float;
private var lastPError: float = 0;

function PidLoop(){
  var pError = desiredAngle - currentAngle; // calculate the proportional error...
  var iError += pError * Time.deltaTime; // the integral error...
  var dError = (pError - lastPError)/ Time.deltaTime; // and the differential error
  lastPError = pError;
  // the torque is the sum of all errors weighted by their gains:
  torque = pGain*pError+iGain*iError+dGain*dError;
  // apply the torque to the object
  ApplyTorque(torque);
}

The function PidLoop must be called at a constant rate, like in Unity's FixedUpdate. currentAngle is the current object angle about the axis of interest (Y, for instance), and desiredAngle is the angle you want to reach. pError is the proportional error: it's just the difference between what you want and the present position. iError is the integral error, a numeric integration of the proportional error, and dError is the differential error, a numeric differentiation of pError. The 3 errors are summed with individual weights, and the resulting value is applied as torque about the same axis currentAngle is measured.
If only pError were used, the final position would never be reached because the force applied is proportional to the error - thus zero error means zero force. To cancel this error while still mantaining some control force, the iError is used: any small pError accumulates in iError over time, creating a force that will eventualy cancel any opposite forces. If there are no opposite forces (as usually happens in rotational PID), the corresponding iGain must be set to zero, or the system will become very unstable. The differential error, dError, is very important in rotational PID, because it becomes negative when the desired angle is getting closer, acting as a break and slowing down the rotation.
In Unity, the big problem is how to get a reliable feedback signal - the controller gets crazy when around 0, or if the other axes are non-zero. Maybe in your 2D engine this error is easier to work around - at least there are no other axes to worry about. Try to adapt an algorithm like this to your case.

more ▼

answered Apr 06 '12 at 01:55 PM

aldonaletto gravatar image

aldonaletto
41.1k 16 42 195

I have to say, anytime I happen across and read your comments I learn alot. Thanks for being a great help @AldoNaletto :D

also 'big up' to all the other regular helpers ( inc Klep =] )

Apr 06 '12 at 02:00 PM alucardj

You, @Duck and @Eric5h5 ... geniuses :D

Apr 06 '12 at 02:19 PM Kleptomaniac

Alright, well to be honest, I was hoping for something that would also work outside of unity... I have a 2d game engine where you would add rotational forces the same way as in unity, and was hoping for a solution that would be applicable for projects in there as well as in my 3d game.

Apr 06 '12 at 07:44 PM Zachary.C.Stewart

Wow, this is brilliant. Thanks!

Dec 02 '12 at 09:23 PM iceydee
(comments are locked)
10|3000 characters needed characters left

You have to assign a rigidbody component to the object and add torque, check this out:

http://unity3d.com/support/documentation/ScriptReference/Rigidbody.AddTorque.html

more ▼

answered Apr 06 '12 at 04:20 AM

garner gravatar image

garner
120 1

I know that. I'm looking for the way to add torque then remove it timed to stop at the right point. So it's more a matter of when to time the stoping point.

Apr 06 '12 at 12:02 PM Zachary.C.Stewart
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x2155
x1864
x1781

asked: Apr 06 '12 at 04:14 AM

Seen: 1435 times

Last Updated: Apr 18 at 01:45 PM