|
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
(comments are locked)
|
|
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).
(comments are locked)
|
|
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. 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
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)
|
|
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 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)
|

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