How to calculate the degrees difference (y-axis) to make an entity look at a target?

I am trying to work out the value in degrees (y-axis) that an entity needs to turn by in order to face another entity.

Stumbling across float4x4.LookAt(float3 eye, float3 target, float3 up) felt promising because I know the eye/entity position, I know the target position and I know which way up is! But… I have no idea what to do with the float4x4 to compare it against my original rotation quaternion to then work out the diffference in degrees. I actually want to know the degrees value in order to feed it into another system. Making the entity turn isn’t important to me.

Plus, I’m trying to do this in Unity.Mathematics so that I can use burst. It looks like the old way had helpers with eulers, LookAt and such.

Some code for context…

Entities.ForEach((Entity entity, in Translation translation, in LocalToWorld localToWorld, in Target target) =>
{
    float4x4 lookRot = float4x4.LookAt(math.forward(rotation.Value), target.translation.Value, localToWorld.Up);
    quaternion lookQuat = new quaternion(lookRot);
    // No idea from here...
});
        public static float GetAngle(float3 a, float3 b)
        {
            return degrees(GetRad(a, b));
        }

        public static float GetRad(float3 a, float3 b)
        {
            return acos(clamp(dot(a, b) / (length(a) * length(b)), -1f, 1f));
        }

After that you can use quaternion.RotateY

1 Like

Thans @vectorized-runner !

How do I use this with the rotation quaternion? My understanding is that I can use that value to determine which way the entity is looking and pass the two floats into your GetAngle method.

I tried this, which works for walking around the target, but not for turning on the spot.

float3 forward = math.forward(rotation.Value); // Also tried localToWorld.Forward
float3 targetTranslation = target.translation.Value

float angle = GetAngle(forward, targetTranslation);

Here’s an example of what I’m aiming for. Entity A is looking directly at the target at 0 degrees, and Entity B is looking away so it’s rotation is about 180 degrees.

6692485--767794--upload_2021-1-6_11-48-32.png

You need to pass current forward vector as first parameter, destination forward vector as second parameter (Target.position - A.position in this case if you want A to look at Target) then rotate A in y axis by the angle rotation.Value = math.mul(rotation.Value, quaternion.RotateY(angle)); (I didn’t test this)

Edit: Also I find rotating by angle very error prone. You can just use quaternion.LookRotation (don’t forget to pass look direction as first parameter, you shouldn’t pass target position), Your other system can get the angle by itself.

1 Like

This is fantastic, I don’t understand how it works but I can pick it apart now to learn.

Thanks for your help @vectorized-runner !

var direction_to_target = target_translation.Value.position - looker_translation.Value;
rotation.Value = quaternion.LookRotation(direction_to_target, float3.up);

You should use LookRotation whereever possible. If you want to turn smoothly, instead of counting up/down angles, use quaternion.slerp.

1 Like