Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Property Drawer: SerializedProperty Disappeared!

Discussion in 'Extensions & OnGUI' started by jister, Apr 25, 2018.

  1. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,649
    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??