Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Assertion failed on expression | New Unity Version Doesn't Like Transforms?

Discussion in 'Scripting' started by Studio_AKIBA, May 25, 2017.

  1. Studio_AKIBA

    Studio_AKIBA

    Joined:
    Mar 3, 2014
    Posts:
    1,427
    This week on "Things that Unity used to be fine with but now no longer likes" we take a look at the script I use to control ALL of the doors in my game, none of which work now.

    Each time I call this script (ask it to open, close or toggle any doors or anything) I get 1 unique error per call, and 1 other error for each object I am trying to adjust.

    The Unique Error
    Code (CSharp):
    1. Assertion failed on expression: 'CompareApproximately(SqrMagnitude(result), 1.0F)'
    2. UnityEngine.Transform:set_localEulerAngles(Vector3)
    3. <DoMovement>c__Iterator0:MoveNext() (at Assets/Scripts/General Interaction/Door/DoorGeneric.cs:81)
    4. UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
    The Per-Object Error
    Code (CSharp):
    1. transform.localRotation assign attempt for 'INSERTOBJECTNAMEHERE' is not valid. Input rotation is { NaN, NaN, NaN, NaN }.
    2. UnityEngine.Transform:set_localEulerAngles(Vector3)
    3. <DoMovement>c__Iterator0:MoveNext() (at Assets/Scripts/General Interaction/Door/DoorGeneric.cs:81)
    4. UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
    The Script
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Events;
    3. #if UNITY_EDITOR
    4. //using UnityEditor;
    5. #endif
    6. using System.Collections;
    7.  
    8. [System.Serializable]
    9. public class Door
    10. {
    11.     public GameObject door;
    12.     public float time = 1.0f;
    13.     public bool rotation;
    14.     public Vector3 open;
    15.     public Vector3 closed;
    16.     public int delaySeconds;
    17.     public AudioClip clip;
    18.     public UnityEvent after;
    19. }
    20.  
    21. public class DoorGeneric : MonoBehaviour {
    22.  
    23.     public Door[] doors;
    24.  
    25.     public bool moving;
    26.     public bool completedPos;
    27.     public bool completedRot;
    28.     public bool closed = true;
    29.  
    30.     public void ToggleDoor()
    31.     {
    32.         if(!moving && closed)
    33.         {
    34.             OpenDoor();
    35.         }
    36.         if(!moving && !closed)
    37.         {
    38.             CloseDoor();
    39.         }
    40.     }
    41.  
    42.     public void OpenDoor()
    43.     {
    44.         if (!moving && closed)
    45.         {
    46.             foreach(Door door in doors)
    47.             {
    48.                 StartCoroutine(DoMovement(door.closed, door.open, door.time, door.door, door.rotation, door.delaySeconds, door.after));
    49.                 door.door.GetComponent<AudioSource>().PlayOneShot(door.clip);
    50.             }
    51.             closed = false;
    52.         }
    53.     }
    54.  
    55.     public void CloseDoor()
    56.     {
    57.         if (!moving && !closed)
    58.         {
    59.             foreach (Door door in doors)
    60.             {
    61.                 StartCoroutine(DoMovement(door.open, door.closed, door.time, door.door, door.rotation, door.delaySeconds, door.after));
    62.                 door.door.GetComponent<AudioSource>().PlayOneShot(door.clip);
    63.             }
    64.             closed = true;
    65.         }
    66.     }
    67.  
    68.     IEnumerator DoMovement(Vector3 startPosition, Vector3 endPosition, float moveTime, GameObject obj, bool rotation, int delay, UnityEvent after)
    69.     {
    70.         moving = true;
    71.         yield return new WaitForSeconds(delay);
    72.         float startTime = Time.time;
    73.         float endTime = startTime + moveTime;
    74.         do
    75.         {
    76.             float timeProgressedPosition = (Time.time - startTime) / moveTime;
    77.             timeProgressedPosition = Mathf.Sin(timeProgressedPosition * Mathf.PI * 0.5f);
    78.             timeProgressedPosition = timeProgressedPosition * timeProgressedPosition * timeProgressedPosition * (timeProgressedPosition * (6f * timeProgressedPosition - 15f) + 10f);
    79.             if (rotation)
    80.             {
    81.                 obj.transform.localEulerAngles = Vector3.Lerp(startPosition, endPosition, timeProgressedPosition);
    82.             }
    83.             else
    84.             {
    85.                 obj.transform.localPosition = Vector3.Lerp(startPosition, endPosition, timeProgressedPosition);
    86.             }
    87.             yield return new WaitForFixedUpdate();
    88.         }
    89.         while (Time.time < endTime);
    90.         after.Invoke();
    91.         moving = false;
    92.     }
    93.  
    94.     public bool isMoving()
    95.     {
    96.         return moving;
    97.     }
    98. }
    Any ideas as to why since Unity 4.8, up to 5.5 it was fine, ans as soon as I update to 5.6, this starts happening... or just how to fix it?
     
    Kurt-Dekker likes this.
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,594
    This has got to do with the Quaternion that is created from your eulerAngles.

    Setting 'localEulerAngles' really just does this:
    Code (csharp):
    1.  
    2.     public Vector3 localEulerAngles
    3.     {
    4.       get
    5.       {
    6.         return this.localRotation.eulerAngles;
    7.       }
    8.       set
    9.       {
    10.         this.localRotation = Quaternion.Euler(value);
    11.       }
    12.     }
    13.  
    From the look of the errors.

    It appears that the euler values you pass in, when converted to Quaternion, result in a quat that doesn't have a magnitude of 1:
    This is a malformed quaternion.

    The next error is when said quaternion is attempted to be assigned to the localRotation, it receives a malformed quat... in this case all NaN... and freaks out.

    Because it's all NaN, either a) unity returns a NaN quat if the mag test fails... or b) why the mag test failed is because the euler angles you supplied were malformed, possibly NaN, inf, or resulted in a division by zero when normalizing.

    Now... this COULD be the result of a bug introduced into Quaternion just before this build. Though, I'm suspect of that as there would be no real reason to modify the underlying code of Quaternion. It's not like the maths of them has changed any time recently... but it could be that; a programmer may have attempted to optimize quats, or maybe they had a slight change when adding support for new frameworks/platforms... but I doubt it. Quality assurance testing should have caught that, Quats are integral parts of the game engine... they're used so often that you'd trip over a bug in them.

    Or, you're passing in bad values.

    Have you checked what the result of your Lerp statement is before it gets assigned to localEulerAngles just as it fails?

    Try changing the code to:
    Code (csharp):
    1.  
    2. var rot = Vector3.Lerp(startPosition, endPosition, timeProgressedPosition);
    3. obj.transform.localEulerAngles = rot;
    4.  
    And put a break point on it for when it fails, and check the value. If rot is weird, the quat will be weird.

    Make sure that the values of door.open, door.closed, or door.time aren't malformed. If for instance door.time = 0, then there's your NaN since you divide by moveTime, which comes from door.time.
     
    Last edited: May 25, 2017