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. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Property Drawer: SerializedProperty Disappeared!

Discussion in 'Immediate Mode GUI (IMGUI)' started by jister, Apr 25, 2018.

  1. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,748
    I have a custom serialized class:
    Code (CSharp):
    1. using System.Reflection;
    2. using UnityEngine;
    3. /// <summary>
    4. /// Uses ReflectorDrawer
    5. /// </summary>
    6. [System.Serializable]
    7. public class Reflector
    8. {
    9.     public GameObject m_Object;
    10.     public Component[] m_Components;
    11.     public MethodInfo[] m_Methods;
    12.     public FieldInfo[] m_Fields;
    13.     public PropertyInfo[] m_Properties;
    14.  
    15.     public int m_CIndex;
    16.     public int m_MIndex;
    17.     public int m_FIndex;
    18.     public int m_PIndex;
    19.  
    20.     public MethodInfo m_GetMethod { get { if( m_MIndex >= 0 ) return m_Methods[m_MIndex]; else return null; } }
    21.     public FieldInfo m_GetField { get { if( m_FIndex >= 0 ) return m_Fields[m_FIndex]; else return null; } }
    22.     public PropertyInfo m_GetProperty { get { if( m_PIndex >= 0 ) return m_Properties[m_PIndex]; else return null; } }
    23.  
    24.     public object m_GetFieldValue { get { return m_GetField.GetValue( m_Components[m_CIndex] ); } }
    25.     public object m_GetPropertyValue { get { return m_GetProperty.GetValue( m_Components[m_CIndex], null ); } }
    26.  
    27.     public Reflector( )
    28.     {
    29.         m_Object = null;
    30.         m_CIndex = m_MIndex = m_FIndex = m_PIndex = -1;
    31.     }
    32. }
    with this as the Drawer:
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using System.Reflection;
    4. using System;
    5. /// <summary>
    6. /// Uses HelperUtility
    7. /// </summary>
    8. [CustomPropertyDrawer( typeof( Reflector ), true )]
    9. public class ReflectorDrawer : PropertyDrawer
    10. {
    11.     Reflector reflector;
    12.     int y;
    13.     GameObject prevObj = null;
    14.     int cInt = -1;
    15.     object parent;
    16.     Component[] components;
    17.     MethodInfo[] methods;
    18.     FieldInfo[] fields;
    19.     PropertyInfo[] properties;
    20.  
    21.     public override float GetPropertyHeight( SerializedProperty property, GUIContent label )
    22.     {
    23.         return base.GetPropertyHeight( property, label ) + y;
    24.     }
    25.  
    26.     public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
    27.     {
    28.         EditorGUI.BeginProperty( position, label, property );
    29.         {
    30.             property.serializedObject.Update( );
    31.             EditorGUI.HelpBox( new Rect( position.x, position.y, position.width, position.height ), "Reflect On Object", MessageType.None );
    32.             SerializedProperty m_Object = property.FindPropertyRelative( "m_Object" );
    33.             EditorGUI.PropertyField( new Rect( position.x, position.y + 15, position.width, 16 ), m_Object );
    34.             if( m_Object == null )
    35.                 return;
    36.             GameObject obj = (GameObject)m_Object.objectReferenceValue;
    37.             if( obj )
    38.             {
    39.                 SerializedProperty cIndex = property.FindPropertyRelative( "m_CIndex" );
    40.                 SerializedProperty mIndex = property.FindPropertyRelative( "m_MIndex" );
    41.                 SerializedProperty fIndex = property.FindPropertyRelative( "m_FIndex" );
    42.                 SerializedProperty pIndex = property.FindPropertyRelative( "m_PIndex" );
    43.                 if( obj != prevObj )
    44.                 {
    45.                     components = obj.GetComponents<Component>( );
    46.                     cIndex.intValue = mIndex.intValue = fIndex.intValue = pIndex.intValue = 0;
    47.                     Reflect( cIndex.intValue );
    48.                     prevObj = obj;
    49.                 }
    50.                 y = 100;
    51.                 if( cInt != cIndex.intValue )
    52.                 {
    53.                     components = obj.GetComponents<Component>( );
    54.                     mIndex.intValue = fIndex.intValue = pIndex.intValue = 0;
    55.                     Reflect( cIndex.intValue );
    56.                     cInt = cIndex.intValue;
    57.                 }
    58.                 cIndex.intValue = EditorGUI.Popup( new Rect( position.x, position.y + 35, position.width, 15 ), cIndex.intValue, HelperUtility.ToStringArray<Component>( components ) );
    59.                 if( components[cIndex.intValue] != null )
    60.                 {
    61.                     if( methods.Length > 0 )
    62.                     {
    63.                         mIndex.intValue = EditorGUI.Popup( new Rect( position.x, position.y + 55, position.width, 15 ), mIndex.intValue, HelperUtility.ToStringArray<MethodInfo>( methods ) );
    64.                         MethodInfo method = methods[mIndex.intValue];
    65.                         //method.
    66.                     }
    67.                     else
    68.                     {
    69.                         EditorGUI.LabelField( new Rect( position.x, position.y + 55, position.width, 15 ), new GUIContent( "No Methods found on this Type" ), EditorStyles.miniBoldLabel );
    70.                     }
    71.                     if( fields.Length > 0 )
    72.                     {
    73.                         fIndex.intValue = EditorGUI.Popup( new Rect( position.x, position.y + 75, position.width * 0.5f, 15 ), fIndex.intValue, HelperUtility.ToStringArray<FieldInfo>( fields ) );
    74.                         object fieldValue = fields[fIndex.intValue].GetValue( components[cIndex.intValue] );
    75.                         EditorGUI.LabelField( new Rect( position.x + position.width * 0.5f, position.y + 75, position.width * 0.5f, 15 ), new GUIContent( " : " + fieldValue ), EditorStyles.miniBoldLabel );
    76.                     }
    77.                     else
    78.                     {
    79.                         EditorGUI.LabelField( new Rect( position.x, position.y + 75, position.width, 15 ), new GUIContent( "No Fields found on this Type" ), EditorStyles.miniBoldLabel );
    80.                     }
    81.                     if( properties.Length > 0 )
    82.                     {
    83.                         pIndex.intValue = EditorGUI.Popup( new Rect( position.x, position.y + 95, position.width * 0.5f, 15 ), pIndex.intValue, HelperUtility.ToStringArray<PropertyInfo>( properties ) );
    84.                         object propValue = properties[pIndex.intValue].GetValue( components[cIndex.intValue], null );
    85.                         EditorGUI.LabelField( new Rect( position.x + position.width * 0.5f, position.y + 95, position.width * 0.5f, 15 ), new GUIContent( " : " + propValue ), EditorStyles.miniBoldLabel );
    86.                     }
    87.                     else
    88.                     {
    89.                         EditorGUI.LabelField( new Rect( position.x, position.y + 95, position.width, 15 ), new GUIContent( "No Properties found on this Type" ), EditorStyles.miniBoldLabel );
    90.                     }
    91.                 }
    92.             }
    93.             else
    94.                 y = 20;
    95.             property.serializedObject.ApplyModifiedProperties( );
    96.         }
    97.         EditorGUI.EndProperty( );
    98.     }
    99.  
    100.     public void Reflect( int index )
    101.     {
    102.         methods = HelperUtility.GetMethods<Component>( components[index] );
    103.         fields = HelperUtility.GetFields<Component>( components[index] );
    104.         properties = HelperUtility.GetProperties<Component>( components[index] );
    105.     }
    106. }
    107.  
    If i just use it as this
    Code (CSharp):
    1. public class ReflectorTest : MonoBehaviour {
    2.  
    3.     public Reflector reflector;
    it works fine.

    but if i try to use it like this and make a Array of AmbientLoop[] in a monobehavior
    Code (CSharp):
    1. [System.Serializable]
    2. public class AmbientLoop
    3. {
    4.     public string clipName;
    5.     public Reflector reflector;
    6.     public AudioClip clip;
    7.     public AudioClip[] m_RandomClips;
    8.     public TimeInDay timeInDay;
    9.  
    10.     public AmbientLoop( )
    11.     {
    12.         reflector = new Reflector( );
    13.     }
    14. }
    if i already had AmbientLoop instances in the list, the property shows up, but if I empty the list in the inspector and try to set a new size i get:
    Code (CSharp):
    1. SerializedProperty m_AmbientLoops.Array.data[0].reflector has disappeared!
    2. UnityEditor.SerializedProperty:FindPropertyRelative(String)
    3. ReflectorDrawer:OnGUI(Rect, SerializedProperty, GUIContent) (at Assets/Scripts/Misc/Editor/ReflectorDrawer.cs:32)
    4. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    5.  
    my guess is the AmbientLoop instance isn't draw yet but it already tries to draw the reflector??
     
  2. N4ma3

    N4ma3

    Joined:
    Nov 1, 2017
    Posts:
    2
    Did you ever find a solution to this problem?

    I'm facing the same thing right now, and it's really confusing...
    There's no documentation on that point, and that doesn't really seem to make any sense.

    So yeah if you succeed to fix this, I would love to know how you did.
     
  3. N4ma3

    N4ma3

    Joined:
    Nov 1, 2017
    Posts:
    2
    Nervermind, I figured it out...

    We don't seem to have the exact same issue, but well the exception thrown was the same.
    So long story short, my problem was because I was manually modifying the size of an Array Serialized Property through the field property.arraySize, but I wasn't applying the modification to the object with property.serializedObject.ApplyModifiedProperties().

    Because I was trying to access the element of the property that comes from the new arraySize, but the object wasn't updated, I was accessing something that doesn't exist yet.
    Well I guess it's something like that, I don't know if I really make sense, but well the fix was this :

    Code (CSharp):
    1. EditorGUI.BeginChangeCheck();
    2.            
    3. property.arraySize = Mathf.Max(0, EditorGUILayout.DelayedIntField("Size", property.arraySize));
    4.            
    5. if (EditorGUI.EndChangeCheck())
    6.         property.serializedObject.ApplyModifiedProperties();
     
    AdamBebko likes this.
  4. Plague_Agent

    Plague_Agent

    Joined:
    Jun 19, 2022
    Posts:
    2
    Same thing happened to me, I added a layer mask, and got that error. I removed the layer mask but it still said the same thing.
    Edit: Fix I just exited the project and did not save the change I made that caused the error.
     
  5. DanW13

    DanW13

    Joined:
    Jan 17, 2019
    Posts:
    1
    Just had this error in unity 2022 , discovered it came from adding a button to a script by dragging to a serialised filed, problem resolved when I changed the button Transition to None, dunno if this will help any else but it was driving me slightly mad!!