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

Get a general object value from SerializedProperty?

Discussion in 'Scripting' started by VipHaLongPro, May 20, 2015.

  1. Syganek

    Syganek

    Joined:
    Sep 11, 2013
    Posts:
    85
    I'm just providing the context with the examples of what I think @simetra meant - please correct me if I'm wrong - beacuse his posts were a little bit confusing in my opinion. I've reproduced the use-case he mentioned as I understand it and had no issues accessing the targetObject. That is why I've decided to add my post here so if anyone else understands it as I have, can see that it does indeed work.

    I just wanna clear up for other readers that we have two different definitions of "directly" in our posts.

    - Mine meant that the field is declared within a class that inherits from UnityEngine.Object and not within a custom class that is then declared in UnityEngine.Object inheritor (as is my understanding of Simetra's case).

    - Your means that no matter where the object is, the field is still a part of UnityEngine.Object, thus is serialized direcly into a YAML file that contains this object - be it .prefab, .asset, or .scene.

    PS:

    I've also tested the .boxedProperty use cases and I'm very satisfied with how they work (in Unity 2022.2) and that they are indeed the solution to this thread. I can get the property as a System.Object, cast it and use it any way I want. For example: get a value of a PropertyField or invoke a method. It works if the class that I'm serializing is defined in UnityEngine.Object directly (my definition :) ), inside a serialized class, as a part of a list, etc.

    upload_2022-12-27_18-56-41.png

    Code I've used for those that want it:

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class TestScript : MonoBehaviour
    5. {
    6.     [SerializeField]
    7.     private SomeProperty _someProperty;
    8.  
    9.     [SerializeField]
    10.     private EmbeddedClass _class;
    11.  
    12.     [SerializeField]
    13.     private List<SomeProperty> _someProperties;
    14.  
    15.     [SerializeField]
    16.     private List<EmbeddedClass> _embeddedClasses;
    17. }
    18.  
    19. [Serializable]
    20. public class SomeProperty
    21. {
    22.     [SerializeField]
    23.     private string _value;
    24.  
    25.     public string Value
    26.     {
    27.         get { return _value; }
    28.     }
    29. }
    30.  
    31. [Serializable]
    32. public class EmbeddedClass
    33. {
    34.     [SerializeField]
    35.     private SomeProperty _someProperty;
    36.  
    37.     [SerializeField]
    38.     private List<SomeProperty> _someProperties;
    39. }
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. [CustomPropertyDrawer(typeof(SomeProperty))]
    5. public class SomePropertyDrawer : PropertyDrawer
    6. {
    7.     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    8.     {
    9.         return property.serializedObject.targetObject == null ? EditorGUIUtility.singleLineHeight : EditorGUIUtility.singleLineHeight * 3;
    10.     }
    11.    
    12.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    13.     {
    14.         if (property.serializedObject.targetObject == null)
    15.         {
    16.             EditorGUI.LabelField(position, new GUIContent("This property does not belong to a UnityEngine.Object"));
    17.         }
    18.         else
    19.         {
    20.             var valueProperty = property.FindPropertyRelative("_value");
    21.            
    22.             var firstRect = new Rect(position);
    23.             firstRect.height = EditorGUIUtility.singleLineHeight;
    24.            
    25.             var secondRect = new Rect(firstRect);
    26.             secondRect.y += EditorGUIUtility.singleLineHeight;
    27.    
    28.             var thirdRect = new Rect(secondRect);
    29.             thirdRect.y += EditorGUIUtility.singleLineHeight;
    30.            
    31.             EditorGUI.LabelField(firstRect, property.serializedObject.targetObject.ToString());
    32.             EditorGUI.PropertyField(secondRect, valueProperty, new GUIContent(property.displayName));
    33.  
    34.             if(property.boxedValue is SomeProperty propertyValue)
    35.             {
    36.                 EditorGUI.LabelField(thirdRect, propertyValue.Value);
    37.             }
    38.             else
    39.             {
    40.                 EditorGUI.LabelField(thirdRect, "It doesn't work.");
    41.             }
    42.         }
    43.     }
    44. }
     
  2. bilalakil

    bilalakil

    Joined:
    Jan 28, 2018
    Posts:
    68
    BTW, this now exists in the Unity.VisualScripting.Core.Editor assembly (which you can freely inspect the source code of to see Unity's own implementation):

    Code (CSharp):
    1. using Unity.VisualScripting;
    2.  
    3. ...
    4.  
    5. object value = serializedProperty.GetUnderlyingValue();
    I'm not sure exactly when this came into existence. I'm using it on 2022.3.6f1 with Visual Scripting 1.8.0.
     
    Bunny83 likes this.
  3. tacticalreindeer

    tacticalreindeer

    Joined:
    Aug 16, 2020
    Posts:
    5