Rigidbody causing transform.position to have a NaN position.

Hello,
I am currently working on a commercial game that involves enabling/disabling GameObjects, that have Colliders and Rigidbodies on them. We got a really odd bug, that unfortunately quite often occurs and breaks the game.

The current behavior is: There is a parent object that represents a “level”. You can switch between the levels by disabling the current level and enabling a new one. A level contains gameobjects, some have rigidbodies attached. The level switch interpolates visually between the levels with a shader, so for a short time both levels exist (This might not be relevant, but i wanted to mention).

Sometimes following error will occur:

2021-07-09 16:09:46.783;116038;1642;1;Error;Unity;Infinity or NaN floating point numbers appear when calculating the transform matrix for a Collider. Scene hierarchy path "(TransformHelper)/1971(Clone)/Desk02/a_1971_210128_05_desk/root/handle02_JNT/Logic";

This error causes the corresponding object to be invisible (object is at NaN position). Rigidbody values like worldcenter, velocity, etc. are also NaN. Objects also dont come back. Position stays NaN. There are actually no behaviours that modify those values in any way or divide through 0.

We found following: Best Practices Guide — NVIDIA PhysX SDK 3.4.0 Documentation
“Overlapping Objects explode” - The provided information did not help though.

We just don’t know how this could occur. Can someone help? Or at least let me understand what happens there?


Hopefully,
likeaguest

True, two objects with Rigidbody crossing each other can fly very far unpredictably. To prevent this, I think it will be enough to make Rigidbody of new objects kinematic while loading a new level.

For example like this:

IEnumerator DisableRigidbodiesWhileLoad(Transform newLevelParent)
{
    var rigidbodies = newLevelParent.GetComponentsInChildren<Rigidbody>().ToList();
    foreach (var rb in rigidbodies)
    {
        if (!rb.isKinematic)
        {
            rb.isKinematic = true;
        }
        else
        {
            rigidbodies.Remove(rb);
        }
    }

    yield return new WaitForSecondsRealtime(2f); // your time

    foreach (var rb in rigidbodies)
    {
        rb.isKinematic = false;
    }
}

But keep in mind that not all existing Rigidbodies are not originally isKinematic. So I remove the originally kinematic Rigidbody from the list.

This coroutine should be called before loading the new level.