Hello!
In this tutorial I will explain how to make a simple List<T> editor for Unity inspector. Lets begin. First we need to create a C# class that will contain the List<T> using UnityEngine; using System.Collections; using System.Collections.Generic; // this is important, the List is in Generic namespace public class ListDisplayer : MonoBehaviour { // create a public public List<CustomClass> exampleList = new List<CustomClass>(); } using UnityEngine; using System.Collections; [System.Serializable] // this exposes public properties in the inspector public class CustomClass { public int intExample; public int sliderExample; public string stringExample; public Color colorExample; public bool booleanExample; public bool toggle; }
Next we need to create our CustomClass, and for the sake of this tutorial it will be as simple as possible.
So far so good.
If you attach the ListDisplayer to a GameObject, you will notice that it will look like this in the Inspector: It is ok, but lets say that the Game Designer of your project needs to edit this list. We can make this look even better and practical for others and yourself to edit. This is possible creating an Editor Script. Here are the steps for creating it: 1) Create a C# Script It's common to name your editor scripts exactly the same as the script itself and include "Editor" in the end. So mine will be called: ListDisplayerEditor.cs After you create the script it will look like this: using UnityEngine; using System.Collections; public class ListDisplayerEditor : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } }
The first thing we need to do is create a folder in the project for this scripts.
As it is a editor script it needs to be in a specific folder. The folder must be named "Editor", and can be in any subdirectory of your project. I like to organize my projects so all my scripts are in a specific folder. This is how my project looks:
Now it's time to make some changes on the script:
using UnityEngine; using UnityEditor; //we need to use some classes from this namespace using System.Collections; // this tells unity we are creating an editor for ListDisplayer [CustomEditor(typeof(ListDisplayer))] // also we need to change "MonoBehaviour" to "Editor" here // this is necessary to overrride the OnInspectorGUI public class ListDisplayerEditor : Editor { public override void OnInspectorGUI() { } }
If you go back in the editor and select that Game Object with ListDisplayer.cs attached you will notice that all the public properties disapeared. That is because when we override the OnInspectorGUI function. We are telling that we no longer want unity to draw the inspector for that class, and we will draw our own now.
Since the function is empty, there is nothing to draw. Now we must include some properties to our class and begin drawing the editor: using UnityEngine; using UnityEditor; using System.Collections; [CustomEditor(typeof(ListDisplayer))] public class ListDisplayerEditor : Editor { ListDisplayer _target; public override void OnInspectorGUI() { // Here we are assigning an instance of target // target is the target of this editor // in wich case is an instance of the class ListDisplayer _target = (ListDisplayer) target; // This will draw a button that if clicked add an instance of CustomClass.cs to our list. if(GUILayout.Button("Add New")) { CustomClass temp = new CustomClass(); _target.exampleList.Add(temp); } } }
The result will be this:
using UnityEngine; using UnityEditor; using System.Collections; [CustomEditor(typeof(ListDisplayer))] public class ListDisplayerEditor : Editor { ListDisplayer _target; private CustomClass _current; public override void OnInspectorGUI() { _target = (ListDisplayer) target; if(GUILayout.Button("Add New")) { CustomClass temp = new CustomClass(); _target.exampleList.Add(temp); } // Loops through the list for(int i = 0; i<_target.exampleList.Count; i++) { // cache current _current = _target.exampleList[i]; // Tell unity that we want to begin drawing all next things in the horizontal // Meaning that all next call will be drawed side-by-side EditorGUILayout.BeginHorizontal(); // Draw expand button, that expands the content of the class if(GUILayout.Button("Expand")) { _current.toggle = !_current.toggle; } _current.toggle = EditorGUILayout.Foldout(_current.toggle, "Custom Class"+(i+1).ToString()); // draw remove button, that if clicked remove current from the list if(GUILayout.Button("Remove")) { _target.exampleList.Remove(_current); break; } // Tell unity we no longer want the horizontal layout. EditorGUILayout.EndHorizontal(); // If the class is expanded if(_current.toggle) { // these are custom functions // The next section will contain their content DrawIntField(); DrawIntSlider(); DrawStringField(); DrawBoolField(); DrawColorField(); } // set the instance to null _current = null; } } } public void DrawIntField() { EditorGUILayout.BeginHorizontal(); // Draw a label for the property EditorGUILayout.LabelField("Int Example"); // Draw an editable int field and update its value _current.intExample = EditorGUILayout.IntField(_current.intExample); EditorGUILayout.EndHorizontal(); } public void DrawIntSlider() { EditorGUILayout.BeginHorizontal(); // draw the label EditorGUILayout.LabelField("Int Slider Example"); // draw a int slider with min 1 and max 10 _current.sliderExample = EditorGUILayout.IntSlider(_current.sliderExample,1, 10); EditorGUILayout.EndHorizontal(); } public void DrawStringField() { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("String Example"); // draw a field to input strings _current.stringExample = EditorGUILayout.TextField(_current.stringExample); EditorGUILayout.EndHorizontal(); } public void DrawBoolField() { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Toggle Example"); // Draw a toggle for a boolean _current.booleanExample = EditorGUILayout.Toggle(_current.booleanExample); EditorGUILayout.EndHorizontal(); } public void DrawColorField() { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Color Example"); // Draw a color picker field _current.colorExample = EditorGUILayout.ColorField(_current.colorExample); EditorGUILayout.EndHorizontal(); }
This is the final result:
This is a simple tutorial but with this knowledge you can apply to much more complex editors. Thank you for reading and feel free to leave a comment in the section bellow! PS: The source for this tutorial
0 Comments
Leave a Reply. |