- Home /
How to make a rigidbody rotate towards an object using physics
So the basics of this is I am trying to make a space ship simulator so I am using physics with no friction or gravity. I am trying to set up some AI to allow ships to travel from 1 point to another. I can rotate my ship, but I am trying to figure out how to make it slow down automatically by apply counter rotational forces so that it will stop and point directly at a target.
If you can help me understand this, or point me to some good sources or some well commented code so I can figure it out it would be greatly appreciated.
EDIT: Ok, so I feel stupid now that I have it working. I knew I was over complicating the process. Basically all I needed to do was to find the angle, apply a thrust, keep track of how long I am firing the thrust for, when I reach halfway start applying an equal but opposite force for the same amount of time. Now to mess around and get forward movement working as well with it using the same priciples. Anyways here is my code now (though i'll need to update it for more than 1 direction of rotation):
#pragma strict
var waypoint:Transform;
var engineThrust:float;
var counterTimer:float;
var startTurn:boolean;
var counterThrust:boolean;
var angle:float;
var startAngle:float;
function Start ()
{
}
function FixedUpdate ()
{
var targetDir = waypoint.transform.position - transform.position;
var forward = transform.forward;
var localTarget = transform.InverseTransformPoint(waypoint.transform.position);
angle = Mathf.Atan2(localTarget.x, localTarget.z) * Mathf.Rad2Deg;
var eulerAngleVelocity : Vector3 = Vector3 (0, angle, 0);
var deltaRotation : Quaternion = Quaternion.Euler(eulerAngleVelocity * Time.deltaTime );
if(Input.GetMouseButtonDown(0))
{
startAngle=angle;
startTurn=true;
}
if(startTurn==true)
{
rigidbody.AddRelativeTorque(Vector3(0,engineThrust*Time.fixedDeltaTime,0));
counterTimer+=1*Time.deltaTime;
}
if(angle<=(startAngle/2))
{
startTurn=false;
counterThrust=true;
}
if(counterThrust==true)
{
if(counterTimer>0)
{
rigidbody.AddRelativeTorque(Vector3(0,-engineThrust*Time.fixedDeltaTime,0));
} else {
counterThrust = false;
counterTimer = 0;
}
counterTimer-=1*Time.deltaTime;
}
}
Answer by Seth-Bergman · Mar 16, 2013 at 05:37 AM
here's a simple sample project,
http://dl.dropbox.com/u/11203897/SampleRigidbodyRotate.zip
I cobbled the script from these links:
http://answers.unity3d.com/questions/15822/how-to-get-the-positive-or-negative-angle-between.html
http://docs.unity3d.com/Documentation/ScriptReference/Rigidbody.MoveRotation.html
http://docs.unity3d.com/Documentation/ScriptReference/Vector3.Angle.html
just open the scene, hit play and drag the sphere around, and the cube should rotate to look at it.. I think this is basically what you want?
I will go back and comment the code, though it is a short script.. I'll leave a comment here when it's cleaned up for a better example!
(for now, here's the ugly version of the script):
var velocity : int = 100;
var sphere : GameObject;
var angle : float;
function FixedUpdate () {
var targetDir = sphere.transform.position - transform.position;
var forward = transform.forward;
var localTarget = transform.InverseTransformPoint(sphere.transform.position);
angle = Mathf.Atan2(localTarget.x, localTarget.z) * Mathf.Rad2Deg;
var eulerAngleVelocity : Vector3 = Vector3 (0, angle, 0);
var deltaRotation : Quaternion = Quaternion.Euler(eulerAngleVelocity * Time.deltaTime );
rigidbody.MoveRotation(rigidbody.rotation * deltaRotation);
}
Thanks! Though this simulates what I want it still gives me a good starting point. This dose not seem to actually use rigidbody.AddRelativeTorque to apply rotational physics, it just seems to grab and turn the cube ins$$anonymous$$d of using physics to spin it. Ideally what I want is to use rigidbody.AddRelativeTorque to start the turn then apply a counter rigidbody.AddRelativeTorque to slow it down so it will stop neatly pointing at the target.
Thanks that helped alot. I think I just needed to see it working so I could see how it should work.
trying to do this with AddRelativeTorque will be trickier, and probably not much difference in the effect, but that's just my opinion.. anyway, glad to help!
Really late here. How would I apply this in 3 dimensions? I'm in the process of experimenting with that test project but any help would be awesome!
Here's what I've got. It works pretty well, but there continues to be some rotation around the x axis. I basically repeated the snippet you had except the second time I applied it to the Z axis. For some reason when I do this again for the X axis, it does not work. ;
function FixedUpdate () {
var targetDir = sphere.transform.position - transform.position;
var localTarget = transform.InverseTransformPoint(sphere.transform.position);
angle = $$anonymous$$athf.Atan2(localTarget.x, localTarget.z) * $$anonymous$$athf.Rad2Deg;
var eulerAngleVelocity : Vector3 = Vector3 (0, angle, 0);
var deltaRotation : Quaternion = Quaternion.Euler(eulerAngleVelocity * Time.deltaTime );
rigidbody.$$anonymous$$oveRotation(rigidbody.rotation * deltaRotation);
angle = $$anonymous$$athf.Atan2(localTarget.y, localTarget.x) * $$anonymous$$athf.Rad2Deg;
eulerAngleVelocity = Vector3 (0, 0, angle);
deltaRotation = Quaternion.Euler(eulerAngleVelocity * Time.deltaTime );
rigidbody.$$anonymous$$oveRotation(rigidbody.rotation * deltaRotation);
// angle = $$anonymous$$athf.Atan2(localTarget.y, localTarget.z) * $$anonymous$$athf.Rad2Deg;
// eulerAngleVelocity = Vector3 (angle, 0, 0);
// deltaRotation = Quaternion.Euler(eulerAngleVelocity * Time.deltaTime );
// rigidbody.$$anonymous$$oveRotation(rigidbody.rotation * deltaRotation);
}