Infinity or nan float numbers appear when calculating matrices for collider

I have the racket object with a boxcollider and rigidbody that follows the vr hand position. The error appears on Quest standalone only (not pc version) and it’s totally random, sometimes after few minutes, sometimes hours.

using UnityEngine;

[System.Serializable]
public partial class Followhand : MonoBehaviour
{
    Rigidbody rb;
    public Transform racket;
    Quaternion rotationDifference;
    Vector3 rotationDifferenceInDegree;

    public virtual void Start()
    {    
        racket = GameObject.Find("Racchetta").transform;    

        rb = GetComponent<Rigidbody>();

        rb.MoveRotation(racket.rotation);
        rb.MovePosition(racket.position);
    }

    void FixedUpdate()
    {
        if (Vector3.Distance(racket.position, rb.position) != 0)
        {
            rb.velocity = (racket.position - rb.position) / Time.fixedDeltaTime;

            rotationDifference = racket.rotation * Quaternion.Inverse(transform.rotation);
            rotationDifference.ToAngleAxis(out float angleInDegree, out Vector3 rotationAxis);
            rotationDifferenceInDegree = angleInDegree * rotationAxis;

            rb.angularVelocity = rotationDifferenceInDegree * Mathf.Deg2Rad / Time.fixedDeltaTime;
        }
    }
}

I can’t see any evident flaw in your code. However, here are some hints and best practices that apply:

In Start, I assume you want to “teleport” the rb to its starting position. You should do so by setting rb.position and rb.rotation directly instead of calling MovePosition / MoveRotation. When you call MovePosition/MoveRotation, the rigidbody will be physically displaced from whatever position it is to reach the specific position/rotation, with all the physics effects of such displacement.

For example, if the rb is at the origin and the racket is 3 m away, then the first frame after Start the rb will calculate a velocity of 3 / 0.02 = 150 m/s (!!). Setting rb.position / rb.rotation avoids this and just teleports the rb to its starting pose.

Use rb.AddForce / rb.AddTorque with the parameter ForceMode.VelocityChange instead of setting rb.velocity and rb.angularVelocity. Modifying rb.velocity / rb.angularVelocity overrides the calculations of the physics solver for the velocities. Best practice is using AddForce/AddTorque to impose a specific velocity like this:

rb.AddForce(expectedVelocity - rb.velocity, ForceMode.VelocityChange);

Another best practice is using Time.deltaTime instead of Time.fixedDeltaTime. When read from within FixedUpdate, Time.deltaTime already returns the value of Time.fixedDeltaTime.

Finally, I’d add a check for NaN after your calculations. Typically, NaN appears in matrices, positions, etc because other calculations have resulted in NaN. For example, you may check that if angleInDegree is NaN like this:

if (float.IsNaN(angleInDegree))
    Debug.LogError("Found a NaN!");

Also, don’t discard that the NaN is being generated somewhere else in your code, then propagated to Rigidbody.position or Rigidbody.rotation and then reaching this code and continue propagating.

1 Like