- Home /
how to display custom [system.serializable ] class in editor window
how to display custom serializable class in custom editor window
I just searched how to achieve this, here is my 2 cents for the next person in line xD
My understanding of the context :
Unity manage to draw something in the inspector because that thing go through SerializedObject/Property that you can imagine like a wrapper around the class you are trying to draw.
And WindowEditor doesn't have those tool accessible (doesn't go through the same functions when drawing).
So it would end up having a tool that draw each property of the class through reflection.
Using a ScriptableObject as a wrapper (that would include the target class) would be a way to have it drawn.
mmmm, not really, unity serializes in the inspector the exact same way we serialize to a file. You don't need to do anything to display custom class in the unity editor, there is nothing fancy behind the serialization of the classes in the inspector.
You can try to display something like :
[System.Serializable] public class TestClass { public int something = 1; }
and in an editor window script what would you use to draw that class ?
I tried multiple things but if it's not at least an Object, this won't work. Or I missed the specific EditorGuiLayout method to do it.
They also have to be of types that can be displayed in the inspector...
Otherwise, you need to create a customer editor.
Answer by ABerlemont · Nov 12, 2021 at 11:50 AM
Some experimentations based on what xxmariofer showed (reflexion & using UnityEngine.Object) and what Pangamini pointed out (window can have serialized field)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
[System.Serializable]
public class Test
{
public int var = 1;
}
[System.Serializable]
public class TestMono : MonoBehaviour
{
public Test testInstance;
private void Awake()
{
testInstance = new Test();
}
}
public class TestSerialWin : EditorWindow
{
[MenuItem("Example/open")]
static void Init()
{
EditorWindow.GetWindow(typeof(TestSerialWin));
}
TestMono carry;
public Test myTestClassInstance;
private void OnEnable()
{
myTestClassInstance = new Test();
}
private void OnGUI()
{
if (myTestClassInstance == null) myTestClassInstance = new Test();
GUILayout.Space(10);
GUILayout.Label("using mono");
if (carry == null)
{
GameObject goc = GameObject.Find("lol");
if (goc == null) goc = new GameObject("lol");
if (goc == null) carry = goc.GetComponent<TestMono>();
else goc.AddComponent<TestMono>();
carry = goc.GetComponent<TestMono>();
}
drawByMonoCarry(carry);
GUILayout.Space(10);
GUILayout.Label("using window");
drawBySerial(this);
GUILayout.Space(10);
GUILayout.Label("using reflection");
drawByReflection();
}
/// <summary>
/// this one is using a suer generated monobehavior to carry the Test instance
/// </summary>
void drawByMonoCarry(MonoBehaviour obj)
{
SerializedObject so = new SerializedObject(obj);
SerializedProperty sp = so.FindProperty("testInstance"); // must match name of variable
EditorGUILayout.PropertyField(sp);
}
/// <summary>
/// this one is using the window editor as carrier of the Test instance
/// </summary>
void drawBySerial(UnityEngine.Object obj)
{
SerializedObject so = new SerializedObject(obj);
SerializedProperty sp = so.FindProperty("myTestClassInstance"); // must match name of variable
EditorGUILayout.PropertyField(sp);
}
/// <summary>
/// this is one more "low level" and all GUILayout stuff must be done by hand
/// </summary>
void drawByReflection()
{
Type te = myTestClassInstance.GetType();
System.Reflection.FieldInfo[] pi = te.GetFields();
//Debug.Log(pi.Length);
foreach (System.Reflection.FieldInfo p in pi)
{
EditorGUILayout.BeginHorizontal();
Type pType = p.GetValue(myTestClassInstance).GetType();
EditorGUILayout.LabelField(pType.ToString());
EditorGUILayout.LabelField(p.Name);
EditorGUILayout.LabelField(p.GetValue(myTestClassInstance).ToString());
EditorGUILayout.EndHorizontal();
}
}
}
Answer by Pangamini · Nov 11, 2021 at 11:33 AM
I'd go with EditorGUILayout.PropertyField. Nothing is stopping you from using that in a custom editor, however you probably need to create and manage the SerializedObject yourself. You could create a SerializedObject from the editor window, if you have a serialized field there (EditorWindows are ScriptableObjects and are serialized in the editor's window layout)
Answer by xxmariofer · Nov 11, 2021 at 12:00 PM
You only need a rerference to the custom class from the custom editor, this example to reproduce: this is the custom class with the variables:
[System.Serializable]
public class Test2
{
public string val { get; set; }
}
this is the Monobehaviour in which the class exist, you dont serialize classes, you serialize instance of that class, so that instance must exist somewhere, in this case, a monobehaviour
using UnityEngine;
[System.Serializable]
public class Test3 : MonoBehaviour
{
private void Awake()
{
t = new Test2();
t.val = "this is an example";
}
public Test2 t;
}
now the editor script:
using UnityEditor;
using UnityEngine;
using System.Collections;
using System;
public class Test : EditorWindow
{
public System.Object source;
[MenuItem("Example/ObjectField Example _h")]
static void Init()
{
EditorWindow.GetWindow(typeof(Test));
}
void OnGUI()
{
EditorGUILayout.BeginVertical();
//source = EditorGUILayout.ObjectField(source, typeof(UnityEngine.Object), true);
source = GameObject.Find("PlaceHolder").GetComponent<Test3>().t;
if (source != null)
{
Type te = source.GetType();
System.Reflection.PropertyInfo[] pi = te.GetProperties();
foreach (System.Reflection.PropertyInfo p in pi)
{
try
{
EditorGUILayout.BeginHorizontal();
Debug.LogWarning(p.Name + " : " + p.GetValue(source));
EditorGUILayout.LabelField(p.Name);
EditorGUILayout.LabelField(p.GetValue(source).ToString());
EditorGUILayout.EndHorizontal();
}
catch
{
}
}
}
EditorGUILayout.EndVertical();
}
}
you can use whatever method you prefer to get the class, this is the simplest example I could think of, the end result:
Without using a custom specific drawer I think this might be the easiest setup to achieve this xD But feels kinda hack-y :)
Without any details its hard to give another answer, probably he only needs to serialize some specifiq classes and overloading the tostring method to return the properties you expected to be shown would be probably a better solution without using reflection, but this is the most generic I could came up with
Your answer
Follow this Question
Related Questions
How to fix unity editor UI, and what dose the icon in the bottom right mean? 2 Answers
What is the best way to draw icons in Unity's Hierarchy window? 1 Answer
How do I code my own custom built blend tree node as seen in the Animation Controller Editor Window? 1 Answer
Custom Editor - Is there any way to detect whether the user is in Prefab editing mode? 1 Answer
Editor Window Views 0 Answers