- Home /
Call a function from CustomPropertyDrawer of Arbitrary class
Hi, So I have this class
public class SomeClass {
public int number;
public void SomeFunction() {}
}
This class is used in many part of my GameObject components, so If i want to create a custom editor for this class, i have to use CustomPropertyDrawer.
[CustomPropertyDrawer(typeof(SomeClass))]
public class ComExpressionEditor : PropertyDrawer
{
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{
// Do something magic here.
}
}
But how i can call my SomeFunction() from there? I've tried property.serializedObject.targetObject
but it makes a compiler error since my SomeClass is an arbitrary (Not Unity.Object) class. Is there any workaround for this?
PropertyDrawer are made change how a field is show in the editor and is not intended to use to edit, but you can get the field value using SerializedProperty.objectReferenceValue.
PropertyDrawers are ment to provide GUI controls to edit the property but through the SerializedProperty and not by direct manipulating objects.
Also "objectReferenceValue" does only work for classes that are serialized on their own (classes that are derived from UnityEngine.Object). So this only applies either for built-in components and classes or for your own classes that are derived from $$anonymous$$onoBehabiour / ScriptableObject.
Answer by Bunny83 · Oct 09, 2016 at 02:19 AM
That's actually not possible with massive useage of reflection as a SerializedProperty only represents the seraializable data and not the actual class instances. Classes derived from UnityEngine.Object are a different story. For those (usually MonoBehaviour or ScriptableObjects) you can use SerializedProperty.objectReferenceValue to get the serialized reference to that object. However if it's just a serializable custom class the serialization system doesn't even know that instance exists. It's content is simply serialized along with the containing MonoBehaviour object (or ScriptableObject).
As i said there are ways to access the "current" instance by using reflection as shown by HiddenMonk and Johannski over here.
Despite it's possible, it's not a good approach. Unity's serialization system abstracted the data from the actual objects. A SerializedObject / SerializedProperty just represents the actual stored data and not the concrete object. Any manipulation is ment to be done through the SerializedProperty class.
I know this system has some limitations when it comes to more complex structures. If you really need to directly access a class instance you would need to use a seperate CustomEditor. PropertyDrawers aren't designed for what you want to do. They are ment to work on the abstracted representation. Keep in mind that a SerializedProperty can actually represent multiple objects at once in case you have more than one object selected.
A custom editor can access the any members of the MonoBehaviour / ScriptableObject through the "target" / "targets" variable(s). In that case you have to handle everything yourself including registering undo operations.
Thank you very much for the link. the Hidden$$anonymous$$onk and Johannski's answer is works great. I was think it doesn't possible (took me hours to understand the code). But anyway, yes, as you warned. If I use a reflection for changing the values, then somehow the SerializedProperty doesn't update it's value. I need to make a distict usage between using SerializedProperty vs. Reflection.
Also +1 (and thanks) for the great explanation you give to me.