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. Dismiss Notice

Accessing single value of different multiple values of a SerializedProperty

Discussion in 'Editor & General Support' started by Winder90, Feb 16, 2017.

  1. Winder90

    Winder90

    Joined:
    Feb 16, 2017
    Posts:
    8
    Hi guys,

    I'm searching for hours and can't find any solution to my problem.

    I'm currently writing a custom editor (inspector) for one of my custom classes. All was fine, until I decided (and burned this decision deeply in my mind :D) to make my inspector working on multiple objects.
    I want something like this:

    Code (CSharp):
    1. public class MyClassEditor : Editor
    2. {
    3.      private SerializedProperty myProperty;
    4.      private bool showProperty;
    5.  
    6.      void OnEnable()
    7.      {
    8.           myProperty = serializedObject.FindProperty("property");
    9.      }
    10.  
    11.      public void OnInspectorGUI()
    12.      {
    13.           if(myProperty.hasMultipleDifferentValues)
    14.           {
    15.                showProperties = EditorGUILayout.Foldout(showProperties);
    16.  
    17.                if(showProperties)
    18.                {
    19.                     for(int i = 0; i < myProperty.ValueCount; i++)
    20.                     {
    21.                          EditorGUILayout.PropertyField(myProperty.GetValue(i));
    22.                     }
    23.                }
    24.           }
    25.           else
    26.           {
    27.                EditorGUILayout.PropertyField(myProperty);
    28.           }
    29.      }
    30. }
    All I could find was iterating through serializedObject.targetObjects, but I had to do this for every property. Therefore, I would have number of objects times number of property iterations. That's kind of slow :D

    Can anyone of you help me, please?

    Winder90
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,557
    You should first consider how should the inspector work with different objects selected? what should it display?
     
  3. Winder90

    Winder90

    Joined:
    Feb 16, 2017
    Posts:
    8
    It's implicitly hidden (maybe too much :D) in the code snippet.

    If multiple objects are selected, I want to have a foldout for each serialized property. On click on one of these foldouts, each property (the same per object) shall be displayed with a property field.
     
  4. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,557
    You could probably achieve this with generic code that iterates over all properties. Your code is actually broken and won't event compile.

    Here's something to get you started. Note that it's not complete, as it also lists some properties that are usually not displayed, the foldout controls all the properties, etc.
    Also, you should mark which class this editor is for (in the CustomEditor attribute):
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3.  
    4. [CustomEditor(typeof(xxxxx))]
    5. [CanEditMultipleObjects]
    6. public class MyEditor : Editor
    7. {
    8.     private bool showProperties;
    9.  
    10.     public override void OnInspectorGUI()
    11.     {
    12.         var sp = serializedObject.GetIterator ();
    13.  
    14.         var isFirst = true;
    15.         var objectCount = serializedObject.targetObjects.Length;
    16.  
    17.         // Iterate over all properties of this serializedObject
    18.         while (sp.NextVisible(isFirst))
    19.         {
    20.             isFirst = false;
    21.  
    22.             // Multiple selected objects
    23.             if (serializedObject.isEditingMultipleObjects)
    24.             {
    25.                 showProperties = EditorGUILayout.Foldout(showProperties, sp.displayName);
    26.  
    27.                 if(showProperties)
    28.                 {
    29.                     // Iterate in reverse, to match the selected object order
    30.                     for (int i = objectCount - 1; i >= 0; i--)
    31.                     {
    32.                         // Get the property on the corresponding serializedObject
    33.                         var o = serializedObject.targetObjects[i];
    34.                         var so = new SerializedObject (o);
    35.  
    36.                         var prop = so.FindProperty (sp.propertyPath);
    37.  
    38.                         EditorGUILayout.PropertyField (prop);
    39.                         so.ApplyModifiedProperties ();
    40.                     }
    41.                 }
    42.             }
    43.             else
    44.             {
    45.                 EditorGUILayout.PropertyField (sp);
    46.                 serializedObject.ApplyModifiedProperties ();
    47.             }
    48.         }
    49.     }
    50. }
     
    forestrf likes this.
  5. Winder90

    Winder90

    Joined:
    Feb 16, 2017
    Posts:
    8
    It seems, I didn't write my question quite understandable.

    1. Thank you for your help.
    2.
    My code snippet was not written to get compiled. It's just a minimal (the smallest I could think of) example of what I want to get.
    3. Your code snippet is exactly the solution I don't want (I wrote it in my first posting):
    Is there a way to get the property-array out of the serialized property?
     
  6. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,557
    that's exactly what i did. Each property is listed once. If you select multiple objects, a foldout is used. when you expand the foldout, you get a property field per selected object.

    I thought that's exactly what you said you wanted.
     
  7. Winder90

    Winder90

    Joined:
    Feb 16, 2017
    Posts:
    8
    Yes, it is. But by doing this, I iterate for each serialized property (1. loop) over each object (2. loop) and search in it for the right property (3. loop).
    I want to access the single properties of the objects directly out of the serialized property. By doing this, I would only iterate over the serialized properties (1. loop) and paint the single properties on the inspector (2. loop).
    2 loops are better than 3, that's why I want to do that. It's faster and the FPS drop is smaller; even when this is in the editor :D
     
  8. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,557
    My code has only 2 loops.
    Feel free to use it as a basis for the solution you're after.

    Also, it's always best to test the performance before over optimizing in advance.
     
  9. Winder90

    Winder90

    Joined:
    Feb 16, 2017
    Posts:
    8
    The third loop is hidden in the FindProperty-method.

    I just realized, that naming it property is maybe confusing. I should name it value. So I have the serialized property storing multiple different values due to multiple object editing. If I call e.g. myProperty.floatValue, it should contain all the different values. I'm searching for something like myProperty.floatValue[0], where I can access the float value of the first selected object.

    This would be much faster than iterating over all serialized objects and calling the FindProperty-method; for each serialized property.

    Or maybe there is a method, that displays the multiple values by giving the serialized property as an argument? I could find EditorGUI.showMixedValues, but it showed not a field per value, like I want it.
     
    Last edited: Feb 19, 2017
  10. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,557
    Ii don't think these APIs work as you wish them to...

    If you want to edit multiple objects at once, you must go over tge selected objects. You will not get an array of "float values" representing the values for all objects. .. Thats not how it works..
     
  11. Winder90

    Winder90

    Joined:
    Feb 16, 2017
    Posts:
    8
    I must really search for every value, even I've already stored them in a serialized property? That's very sad :-(

    But thanks for your help :)
     
  12. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,557
    That's just how it works. use the code i posted above, it will do exactly what you need.