Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Invalid iteration - (You need to stop calling Next when it returns false) - SerializedProperty

Discussion in 'Scripting' started by thrmotta, Dec 9, 2014.

  1. thrmotta

    thrmotta

    Joined:
    May 27, 2014
    Posts:
    32
    Hello!

    Ive been getting the following error message:
    Code (CSharp):
    1. Invalid iteration - (You need to stop calling Next when it returns false)
    Which I can barely find anything about on the internet.

    This error occurs when creating a PropertyField on a Custom Editor class.
    All the variables used at the PropertyFields (which causes the erros) are Vector3 and are inited on declaration with Vector3.zero. Ive tried to Debug.Log the SerializedProperty vars and all of them are being prited as 0, 0, 0, even when I change them at the Inspector. Actually, because of this error the numbers at the vector3 fields keeps changing every few seconds to random values.

    This is the full class which is causing the error (I commented the lines that gives me this error):
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEditor;
    5.  
    6. namespace SimVR
    7. {
    8.     [CanEditMultipleObjects, CustomEditor(typeof(FunctionsMask))]
    9.     public class FunctionsMaskEditor : Editor
    10.     {      
    11.         private FunctionsMask _script { get { return target as FunctionsMask; }}
    12.        
    13.         int nInfo = 6;
    14.         string[] _infoNames = new string[6]{ "Linear Velocity",
    15.             "Angular Velocity",
    16.             "Linear Acceleration",
    17.             "Angular Acceleration",
    18.             "Force",
    19.             "Torque" };
    20.        
    21.         SerializedProperty _functionsMaskProp;
    22.        
    23.         SerializedProperty _linearVelocityProp;
    24.         SerializedProperty _angularVelocityProp;
    25.         SerializedProperty _linearAccelerationProp;
    26.         SerializedProperty _angularAccelerationProp;
    27.         SerializedProperty _forceProp;
    28.         SerializedProperty _torqueProp;
    29.        
    30.         SerializedProperty _chosenFunctionsProp;
    31.        
    32.         void OnEnable()
    33.         {
    34.             _functionsMaskProp = serializedObject.FindProperty("_functionsMask");
    35.            
    36.             _linearVelocityProp         = serializedObject.FindProperty("_linearVelocity");
    37.             _angularVelocityProp        = serializedObject.FindProperty("_angularVelocity");
    38.             _linearAccelerationProp        = serializedObject.FindProperty("_linearAcceleration");
    39.             _angularAccelerationProp     = serializedObject.FindProperty("_angularAcceleration");
    40.             _forceProp                     = serializedObject.FindProperty("_force");
    41.             _torqueProp                 = serializedObject.FindProperty("_torque");
    42.            
    43.             _chosenFunctionsProp         = serializedObject.FindProperty("_chosenFunctions");
    44.         }
    45.        
    46.        
    47.         public override void OnInspectorGUI ()
    48.         {
    49.             serializedObject.Update ();
    50.             EditorGUILayout.Space ();
    51.             EditorGUILayout.Space ();
    52.            
    53.             _chosenFunctionsProp.ClearArray ();
    54.             for ( int i = 0; i < _infoNames.Length; i++ )
    55.             {
    56.                 if( (_functionsMaskProp.intValue >> i & 0x1) == 1 )
    57.                 {
    58.                     _chosenFunctionsProp.arraySize++;
    59.                     SerializedProperty elementProperty = _chosenFunctionsProp.GetArrayElementAtIndex( _chosenFunctionsProp.arraySize - 1 );
    60.                     elementProperty.stringValue = _infoNames[i];
    61.                 }
    62.             }
    63.            
    64.             EditorGUILayout.Space ();
    65.            
    66.             EditorGUI.indentLevel++;
    67.            
    68.             for( int i = 0; i < nInfo; i++ )
    69.             {
    70.                 if( chosenFunctionsContains( _infoNames[i] ) )
    71.                 {                  
    72.                     switch ( i )
    73.                     {
    74.                     case 0:
    75.                       EditorGUILayout.PropertyField( _linearVelocityProp); //Error can happen here
    76.                         break;
    77.                     case 1:
    78.                         EditorGUILayout.PropertyField( _linearAccelerationProp ); //Error can happen here
    79.                         break;
    80.                     case 2:
    81.                        EditorGUILayout.PropertyField( _angularVelocityProp); //Error can happen here
    82.                         break;
    83.                     case 3:
    84.                         EditorGUILayout.PropertyField( _angularAccelerationProp); //Error can happen here
    85.                         break;
    86.                     case 4:
    87.                        EditorGUILayout.PropertyField( _forceProp); //Error can happen here
    88.                         break;
    89.                     case 5:
    90.                       EditorGUILayout.PropertyField( _torqueProp); //Error can happen here
    91.                         break;
    92.                     }
    93.                 }
    94.             }
    95.            
    96.             EditorGUI.indentLevel--;
    97.            
    98.             EditorGUILayout.Space ();
    99.            
    100.             if( _chosenFunctionsProp.arraySize > 0 )
    101.             {
    102.                 EditorGUILayout.BeginHorizontal();
    103.                 GUILayout.Space( 10 );
    104.                 if( GUILayout.Button ( "Apply" ) )
    105.                 {  
    106.                     foreach( FunctionsMask currFM in targets )
    107.                     {
    108.                         LinkActuator currLA = currFM.GetComponentInParent<LinkActuator>();
    109.                         Link linkScript = currLA.gameObject.GetComponent<Link>();
    110.                         for( int i = 0; i < nInfo; i++ )
    111.                         {
    112.                             if( chosenFunctionsContains( _infoNames[i] ) )
    113.                             {
    114.                                 if      ( i == 0 )    linkScript.ApplyLinearVelocity            ( currLA._infoToApply.getInfoToApply( i ) );
    115.                                 else if ( i == 1 )    linkScript.ApplyAngularVelocity         ( currLA._infoToApply.getInfoToApply( i ) );
    116.                                 else if ( i == 2 )    linkScript.ApplyLinearAcceleration         ( currLA._infoToApply.getInfoToApply( i ) );
    117.                                 else if ( i == 3 )    linkScript.ApplyAngularAcceleration     ( currLA._infoToApply.getInfoToApply( i ) );
    118.                                 else if ( i == 4 )    linkScript.ApplyForce                     ( currLA._infoToApply.getInfoToApply( i ) );
    119.                                 else if ( i == 5 )    linkScript.ApplyTorque                     ( currLA._infoToApply.getInfoToApply( i ) );
    120.                             }
    121.                         }
    122.                     }
    123.                    
    124.                 }
    125.                 EditorGUILayout.EndHorizontal();
    126.                 EditorGUILayout.Space ();
    127.             }
    128.            
    129.             serializedObject.ApplyModifiedProperties ();
    130.         }
    131.        
    132.         bool chosenFunctionsContains( string name )
    133.         {
    134.             for ( int i = 0; i < _chosenFunctionsProp.arraySize; i++ )
    135.             {
    136.                 SerializedProperty elementProperty = _chosenFunctionsProp.GetArrayElementAtIndex( i );
    137.                 if ( name == elementProperty.stringValue )
    138.                     return true;
    139.             }
    140.            
    141.             return false;
    142.         }
    143.     }
    144. }
    What am I doing wrong?

    Thank you for your time!
     
  2. thrmotta

    thrmotta

    Joined:
    May 27, 2014
    Posts:
    32
    I still do not fully understand why is it working now, but after commenting out all the [HideInInspector] tags, the error vanished!
     
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,199
    wat

    That makes no sense. Especially since you're not in an iterator where the error used to happen. There must be some deep magic happening somewhere.
     
  4. thrmotta

    thrmotta

    Joined:
    May 27, 2014
    Posts:
    32
    Thats all the editor code really..

    This is the regular class (spoiler: nothing obscure going on here):

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using System;
    4.  
    5. namespace SimVR
    6. {
    7.     public class FunctionsMask : MonoBehaviour
    8.     {      
    9.         public Vector3 _linearVelocity = Vector3.zero;
    10.         public Vector3 _angularVelocity = Vector3.zero;
    11.         public Vector3 _linearAcceleration = Vector3.zero;
    12.         public Vector3 _angularAcceleration = Vector3.zero;
    13.         public Vector3 _force = Vector3.zero;
    14.         public Vector3 _torque = Vector3.zero;
    15.  
    16.         public List<string> _chosenFunctions = new List<string> ();      
    17.  
    18.         public int _functionsMask = 0;
    19.  
    20.         public Vector3 get(int idx)
    21.         {
    22.             switch ( idx )
    23.             {
    24.             case 0:
    25.                 return _linearVelocity;
    26.             case 1:
    27.                 return _angularVelocity;
    28.             case 2:
    29.                 return _linearAcceleration;
    30.             case 3:
    31.                 return _angularAcceleration;
    32.             case 4:
    33.                 return _force;
    34.             case 5:
    35.                 return _torque;
    36.             default:
    37.                 Debug.LogError ( "Parametro de entrada incorreto!" );
    38.                 return Vector3.zero;
    39.             }
    40.         }
    41.  
    42.         public void set( Vector3 infoToApply, int idx )
    43.         {
    44.             switch ( idx )
    45.             {
    46.             case 0:
    47.                 _linearVelocity = infoToApply;
    48.                 break;
    49.             case 1:
    50.                 _angularVelocity = infoToApply;
    51.                 break;
    52.             case 2:
    53.                 _linearAcceleration = infoToApply;
    54.                 break;
    55.             case 3:
    56.                 _angularAcceleration = infoToApply;
    57.                 break;
    58.             case 4:
    59.                 _force = infoToApply;
    60.                 break;
    61.             case 5:
    62.                 _torque = infoToApply;
    63.                 break;
    64.             default:
    65.                 Debug.LogError ( "Parametro de entrada incorreto!" );
    66.                 break;
    67.             }
    68.         }
    69.      
    70.         public void set( Vector3[] infoToApply )
    71.         {
    72.             _linearVelocity = infoToApply[0];
    73.             _angularVelocity = infoToApply[1];
    74.             _linearAcceleration = infoToApply[2];
    75.             _angularAcceleration = infoToApply[3];
    76.             _force = infoToApply[4];
    77.             _torque = infoToApply[5];
    78.         }
    79.  
    80.     }
    81. }
    82.  
    And this class was called at the OnInspectorGUI of another editor class, like this:

    Code (CSharp):
    1. public override void OnInspectorGUI ()
    2.         {
    3.             DrawDefaultInspector ();
    4.  
    5.             foreach ( LinkActuator currLA in targets )
    6.             {
    7.                 if ( currLA.GetComponent<FunctionsMask>() == null )
    8.                 {
    9.                     currLA.gameObject.AddComponent<FunctionsMask>();
    10.                 }
    11.  
    12.                 currLA._infoToApply = currLA.GetComponent<FunctionsMask>();
    13.                 currLA._infoToApply.hideFlags = HideFlags.None;
    14.  
    15.                 currLA._infoToApply._functionsMask = _functionsMaskProp.intValue;
    16.  
    17.             }
    18.  
    19.             _functionsMaskEditor = Editor.CreateEditor( _script._infoToApply );
    20.             if ( _functionsMaskEditor != null )
    21.                 _functionsMaskEditor.OnInspectorGUI();
    22.  
    23.          
    24.             serializedObject.ApplyModifiedProperties ();
    25. }
    Thats all of it. So far my understanding of this error is that with the HideInInspector tag the error described at http://answers.unity3d.com/questions/199691/nonserialized-vs-hideininspector-question.html occurs, which is the following:
     
  5. tgouala-wellfiredLtd

    tgouala-wellfiredLtd

    Joined:
    Jun 8, 2013
    Posts:
    99
    Not sure if it is an expected behaviour in Unity, but this seems to occur only with Vector3 and Vector2.
    If you still need to keep [HideInInspector] on your variable, you can use :
    Code (CSharp):
    1. serializedObject.FindProperty("myVector").vector3Value = EditorGUILayout.Vector3Field(new GUIContent("aVector"), serializedObject.FindProperty("myVector").vector3Value);
    Instead of
    Code (CSharp):
    1. EditorGUILayout.PropertyField(serializedObject.FindProperty("myVector"), new GUIContent("aVector"), false);
     
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I have a theory. Mostly hand wavy stuff here, don't read too much into it.

    Unity does some weird stuff when it serializes structs. It doesn't handle uninitialized structs, instead it initializes them with default values in the background. One of the easy ways to break it is expose struct with a serializable member of its own type. Unity goes into an infinite loop. I suspect the OP has found some similar edge case that breaks serialization.