Search Unity

Exceptions when changing Time.timeScale

Discussion in 'Cinemachine' started by bromanz, Jan 19, 2018.

  1. bromanz

    bromanz

    Joined:
    Jan 30, 2017
    Posts:
    4
    In our application we have the option to pause every physics behaviour by setting Time.timeScale = 0; and unpausing it by restoring it to Time.timeScale = 1;. During the pause, CM doesn't work, which is expected. However, immediately after restoring Time.timeScale to 1, numerous exceptions are thrown:

    Code (CSharp):
    1. Assertion failed: Assertion failed on expression: 'CompareApproximately(det, 1.0F, .005f)'
    2. UnityEngine.Quaternion:FromToRotation(Vector3, Vector3)
    3. Cinemachine.Utility.PositionPredictor:PredictPosition(Single) (at Assets/Cinemachine/Base/Runtime/Core/Predictor.cs:64)
    4. Cinemachine.CinemachineComposer:GetLookAtPointAndSetTrackedPoint(Vector3) (at Assets/Cinemachine/Base/Runtime/Components/CinemachineComposer.cs:132)
    5. Cinemachine.CinemachineComposer:PrePipelineMutateCameraState(CameraState&) (at Assets/Cinemachine/Base/Runtime/Components/CinemachineComposer.cs:151)
    6. Cinemachine.CinemachineVirtualCamera:CalculateNewState(Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineVirtualCamera.cs:420)
    7. Cinemachine.CinemachineVirtualCamera:UpdateCameraState(Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineVirtualCamera.cs:128)
    8. Cinemachine.CinemachineCore:UpdateVirtualCamera(ICinemachineCamera, Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Core/CinemachineCore.cs:237)
    9. Cinemachine.CinemachineCore:UpdateAllActiveVirtualCameras(Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Core/CinemachineCore.cs:172)
    10. Cinemachine.CinemachineBrain:UpdateVirtualCameras(UpdateFilter, Single) (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineBrain.cs:445)
    11. Cinemachine.CinemachineBrain:LateUpdate() (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineBrain.cs:399)
    12.  
    13.  
    14. Assertion failed: Assertion failed on expression: 'fRoot >= Vector3f::epsilon'
    15. UnityEngine.Quaternion:FromToRotation(Vector3, Vector3)
    16. Cinemachine.Utility.PositionPredictor:PredictPosition(Single) (at Assets/Cinemachine/Base/Runtime/Core/Predictor.cs:64)
    17. Cinemachine.CinemachineComposer:GetLookAtPointAndSetTrackedPoint(Vector3) (at Assets/Cinemachine/Base/Runtime/Components/CinemachineComposer.cs:132)
    18. Cinemachine.CinemachineComposer:PrePipelineMutateCameraState(CameraState&) (at Assets/Cinemachine/Base/Runtime/Components/CinemachineComposer.cs:151)
    19. Cinemachine.CinemachineVirtualCamera:CalculateNewState(Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineVirtualCamera.cs:420)
    20. Cinemachine.CinemachineVirtualCamera:UpdateCameraState(Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineVirtualCamera.cs:128)
    21. Cinemachine.CinemachineCore:UpdateVirtualCamera(ICinemachineCamera, Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Core/CinemachineCore.cs:237)
    22. Cinemachine.CinemachineCore:UpdateAllActiveVirtualCameras(Vector3, Single) (at Assets/Cinemachine/Base/Runtime/Core/CinemachineCore.cs:172)
    23. Cinemachine.CinemachineBrain:UpdateVirtualCameras(UpdateFilter, Single) (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineBrain.cs:445)
    24. Cinemachine.CinemachineBrain:LateUpdate() (at Assets/Cinemachine/Base/Runtime/Behaviours/CinemachineBrain.cs:399)
    25.  
    26. Look rotation viewing vector is zero
    If you're using a following CM virtual camera utilizing a Transposer and Composer, the camera ends up jittering for 1-2 secs after unpausing due to the exceptions.

    My current workaround solution includes the following changes in Predictor.cs:58

    Code (CSharp):
    1. Vector3 vel = (m_Velocity.IsEmpty() || !IsValid(m_Velocity.Value())) ? Vector3.zero : m_Velocity.Value();
    2. Vector3 accel = (m_Accel.IsEmpty() || !IsValid(m_Accel.Value())) ? Vector3.zero : m_Accel.Value();
    The velocity and acceleration are now also set to Vector3.zero if m_Velocity or m_Accel values are not valid, i.e. their vectors include one float which is infinity or NaN. This is the case after restoring Time.timeScale = 1 (and this could maybe happen in other edge cases too I guess?). Below I added the function:

    Code (CSharp):
    1. private bool IsValid(Vector3 v)
    2. {
    3.   return !float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z) && !float.IsInfinity(v.x) && !float.IsInfinity(v.y) && !float.IsInfinity(v.z);
    4. }
    5.  
    Hope that this helps someone else out and a similar fix will playback into the next CM version :)
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    Hey @bromanz Thanks for posting this!

    While your fix will make the exceptions go away, it's probably better to correct the error at the source. This happens in PositionPredictor.AddPosition() and PositionPredictor.PredictPosition(), when these methods divide by deltaTime which, if zero, will generate NaNs. Probably it's best if these methods simply check for deltaTime==0 before dividing.

    We will include a fix in the next release of CM.

    For now, you can patch Predictor.cs with these replacement methods:
    Code (CSharp):
    1.         public void AddPosition(Vector3 pos)
    2.         {
    3.             if (IsEmpty)
    4.                 m_Velocity.AddValue(Vector3.zero);
    5.             else if (Time.deltaTime > Vector3.kEpsilon)
    6.             {
    7.                 Vector3 vel = m_Velocity.Value();
    8.                 Vector3 vel2 = (pos - m_Position) / Time.deltaTime;
    9.                 m_Velocity.AddValue(vel2);
    10.                 m_Accel.AddValue(vel2 - vel);
    11.             }
    12.             m_Position = pos;
    13.         }
    14.  
    15.         public Vector3 PredictPosition(float lookaheadTime)
    16.         {
    17.             Vector3 pos = m_Position;
    18.             if (Time.deltaTime > Vector3.kEpsilon)
    19.             {
    20.                 int numSteps = Mathf.Min(Mathf.RoundToInt(lookaheadTime / Time.deltaTime), 6);
    21.                 float dt = lookaheadTime / numSteps;
    22.                 Vector3 vel = m_Velocity.IsEmpty() ? Vector3.zero : m_Velocity.Value();
    23.                 Vector3 accel = m_Accel.IsEmpty() ? Vector3.zero : m_Accel.Value();
    24.                 for (int i = 0; i < numSteps; ++i)
    25.                 {
    26.                     pos += vel * dt;
    27.                     Vector3 vel2 = vel + (accel * dt);
    28.                     accel = Quaternion.FromToRotation(vel, vel2) * accel;
    29.                     vel = vel2;
    30.                 }
    31.             }
    32.             return pos;
    33.         }
    Thanks again!
     
    Last edited: Jan 19, 2018
  3. paulindrome

    paulindrome

    Joined:
    Mar 10, 2018
    Posts:
    36
    Sorry for digging up an old thread but this problem seems to still be around.
    I've tried working around this with various bruteforce tricks but nothing saves me from having to use a timescale of 0.005f or lower instead of actually pausing the game with a timescale of 0 flat.

    (Btw. I love using cinemachine. No idea how I ever got by without it.)
     
  4. Ian094

    Ian094

    Joined:
    Jun 20, 2013
    Posts:
    1,548
    Does checking "Ignore Time Scale" in the Cinemachine Brain help?

    I know, Cinemachine is amazing!
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    @paulindrome What version of CM are you using?
    Did you apply the patch I posted above? That should make the exceptions go away.
    No need to set IgnoreTimeScale in the brain.
     
  6. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    Same problem here on cinemachine 2.1.10 and unity 2017.4.3f1

    Trying to patch it now... brb

    Result: The patch works perfectly!

    @Gregoryl thank you.
     
    Last edited: Jul 5, 2018