Search Unity

  1. Full schedule for #UniteBerlin is now available! Featuring talks on our roadmap, hands-on labs and much more! Check it out!
    Dismiss Notice
  2. Unity 2018.1 has arrived! Read about it here
    Dismiss Notice
  3. Scriptable Render Pipeline improvements, Texture Mipmap Streaming, and more! Check out what we have in store for you in the 2018.2 Beta.
    Dismiss Notice
  4. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  5. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  6. 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,620
    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. ReflectorDrawer:OnGUI(Rect, SerializedProperty, GUIContent) (at Assets/Scripts/Misc/Editor/ReflectorDrawer.cs:32)
    3. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    4.  
    my guess is the AmbientLoop instance isn't draw yet but it already tries to draw the reflector??