How does Rigidbody2D read transform rotation?

When you add a Rigidbody2D to a GameObject, and rotate the transform at edit time or runtime, the Rigidbody2D updates it’s .rotation value to match the transform.

How exactly is this calculated? It seems to not just be .eulerAngles.z, since you can get pretty different values from that if you rotate the transform around other axes than the z-axis.

The reason I’m asking is because I have a script that does some things relative to a Rigidbody2D’s rotation, and I’m drawing some gizmos to show the directions. In one instance, the Rigidbody2D is added at runtime, so I want to show the gizmos relative to the rotation the body will have when that happens. Any help appreciated!

Basically it has to do some complex Quaternion calculations when it reads the Z or writes the Z which is its only degree of rotational freedom.

The localToWorldMatrix that transforms a Collider2D shape into world-space, relative to any Rigidbody2D (if it exists) can be found here: Unity - Scripting API: Collider2D.localToWorldMatrix

There’s also Unity - Scripting API: Rigidbody2D.localToWorldMatrix

I’m not sure if that gives you what you need exactly though.

Probably the best way to show you the composition/decomposition of Z when dealing with quaternions is to show you this bit of code that uses the Unity math package. Maybe this will be of some use as it does essentially the same thing as is done in the C++ code.

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static quaternion ToPositiveQuaternion(quaternion q)
{
    return q.value.w < 0.0f ? -q.value : q.value;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ZRotationFromQuaternion(quaternion q)
{
    var positiveQ = ToPositiveQuaternion(q);
    return 2.0f * math.atan2(positiveQ.value.z, positiveQ.value.w);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static quaternion ZQuaternionFromQuaternion(quaternion q)
{
    return QuaternionFromZRotation(ZRotationFromQuaternion(q));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static quaternion QuaternionFromZRotation(float rotation)
{
    return new quaternion(0.0f, 0.0f, math.sin(0.5f * rotation), math.cos(0.5f * rotation));
}
2 Likes

Thanks for the input!

Those matrices are 2D Physics → Transform, while I need the other way around, ie “if I added a Rigidbody2D to this transform, what would it’s rotation value be?”

I can fudge it since these objects are currently expected to only be rotated on the z-axis anyways, but I want to not have to go back and fix things if that’s not the case anymore.

(this was an answer to the first of your two posts!)

Maybe we just passed each other in posting; does the code snippet above help you with that i.e. composition/decomposition of Z?

If not, I think I’m not following what you need.

1 Like

Yeah, the code snippet you posted is perfect. I seem to get the exact same values on my test script and on a Rigidbody2D if I do this:

using System.Runtime.CompilerServices;

using Unity.Mathematics;

using UnityEngine;

[ExecuteAlways, RequireComponent(typeof(Rigidbody2D))]
public class TestScript : MonoBehaviour
{
    public float expectedZ;

    void Update()
    {
        expectedZ = Mathf.Rad2Deg * ZRotationFromQuaternion(ToPositiveQuaternion(transform.rotation));
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static quaternion ToPositiveQuaternion(quaternion q)
    {
        return q.value.w < 0.0f ? -q.value : q.value;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static float ZRotationFromQuaternion(quaternion q)
    {
        var positiveQ = ToPositiveQuaternion(q);
        return 2.0f * math.atan2(positiveQ.value.z, positiveQ.value.w);
    }
}

9757062--1397169--upload_2024-4-8_15-14-13.png

9757062--1397172--upload_2024-4-8_15-14-22.png

Thanks a lot!

1 Like

Sorry about the awful method names. :wink:

Glad it works.

1 Like