What is the most accurate method of calculating total rotations of a rigidbody?

I want to calculate a rigidbody’s total rotations in the most accurate manner possible in order to simulate robot encoders (encoders calculate the total amount of rotations of an axle without resetting once the axle makes a full rotation, e.g. the encoder gives an output of 0, 360 degrees, 720 degrees, and so on.) Luckily, I only wish to calculate rotations along one axis. However, I cannot simply read from transform.eulerAngles, as this number resets to zero or inverts itself after reaching a certain threshold. This also means I cannot reliably use the change in rotation each frame and add it to a total, as I need to know the direction which the rigidbody rotated as well. I’m also unsure about using the angular velocity of the rigidbody and multiplying it by changes in time, as I do not know if this mirrors the calculations by Unity’s physics engine and I want the calculation to be as accurate as possible. I also want the calculations to stay accurate at high RPMs, and it seems unlikely to me that an angular velocity calculation would be accurate if the rigidbody encounters an object. Does anyone have a accurate method of getting a rigidbody’s total rotation, keeping in mind high rotational speeds and collisions? Thanks.

The easiest way is this (for the Y axis)

FixedUpdate(){
    totalRot += rigidbody.angularVelocity.y * Time.fixedDeltaTime;
}

The possible errors will be minuscule, and caused by the fact that the rotation of a rigidbody may be stopped mid-physics-frame by a collision, which means that every frame where there is a collision you may have an error of 50% of the delta velocity average.


This is the other option, more precise, but can fail if the angular velocity gets ludicrously high.

float yRot = rigidbody.rotation.eulerAngles.y;
float angle = Mathf.Angle(yRot, yRotPrev);
if (yRot > yRotPrev)
    totalRot += angle;
else
    totalRot -= angle;
yRotPrev = yRot;

Or this shorter but untested code

totalRot += Mathf.repeat(yRot - prevRot, 360f) % 180f;

Both solutions could be put together and work in absurd scenarios, but it’s really unnecessary.