Adding torque to make a rigid body face another rigid body.

Given RigidBody a and RigidBody b. I want a to face b, using physics.

I can calculate the desired direction from a to b. Normalize(b.position - a.position). Now, what forces do I apply to make it turn toward that direction?

Unity pushes (almost pigeon holes) the developer to use physics whenever possible. Being a nice prebuilt engine, I would hope Unity has something like the following function built-in. The code below is what I used in another physics game in another language to achieve the same goal.

// this is something like correction = wantedPosition - position
Matrix q = Matrix.Inverse(desiredOrientation) * body.Orientation; 
Vector3 axis;

float x = q.M32 - q.M23;
float y = q.M13 - q.M31;
float z = q.M21 - q.M12;

float r = Math.Sqrt(x * x + y * y + z * z);
float t = q.M11 + q.M22 + q.M33;

float angle = (float)Math.Atan2(r, t - 1);
axis = new Vector3(x, y, z) * angle;

if (r != 0.0f) axis = axis * (1.0f / r);
            
// 80.0f is the spring value "k"
body.AddTorque(Vector3.Transform(axis, Matrix.Inverse(body.InverseInertiaWorld)) * springValueK);
            
// also apply some damping
body.AngularVelocity *= damping;

I am really hoping there is some easy way to do this. I really shouldn’t have to rip apart matrices to do such a common physics operation.

Thanks!

2 Answers

2

Give a a ConfigurableJoint, set to drive the rotation. In FixedUpdate, set configurableJoint.targetRotation to Quaternion.LookRotation(b.position - a.position). You can set properties on the ConfigurableJoint to change the drive mode and speed (play with the drive mode, it really makes a difference with large rotation changes). And yes, Unity does its best to keep you from having to rip matrices apart. :slight_smile:

Use the cross product. Its the key.

obj1.rigidbody.angularVelocity=Vector3.zero;
obj1.rigidbody.AddTorque(Vector3.Cross(obj1.transform.up, obj2.transform.up)*10);

this will slowly align obj1’s up vector with obj2’s. Zeroing the angular velocity is required to not let the obj1 to get too accelerated and rotate further than needed.