In this Unity C# tutorial you will create a custom visualization for arrays and lists in the editor.
Specify a space-separated list of assembly names as parameters for Unity to ignore on automatic updates. The space-separated list of assembly names is optional: pass the command line options without any assembly names to ignore all assemblies, as in example 1. Example 1 unity.exe -disable-assembly-updater Example 2. So in Unity I'm making Snake, and to do that I've a list which houses all the tail elements from the Snake (this was implemented by the NoobTuts tutorial on snake just FYI). I'm find with adding stuff and removing stuff from the list, HOWEVER, I do have an issue with part of the removal.
You will learn to- create a custom editor
- use
SerializedObject
- manipulate a
SerializedProperty
that represents an array or list - use an enumeration for option flags
- use GUI buttons
This tutorial comes after the Custom Data tutorial.
This tutorial is for Unity version 4.3 and above.
Creating Test Data
Unity's default way to show lists is serviceable, but it's possible to find yourself wanting for an alternative. The specifics can vary from case to case. So it would be useful if we could use a mix of different visualizations. It is possible to do this by adding attributes to variables that specify how the editor should show them.We start with the finished Custom Data tutorial project, or by creating a new empty project and importing custom-data.unitypackage.
Then we create a new test script named ListTester with some test arrays, and make a new prefab and prefab instance with it, so we can see it all works as expected.
Creating a Custom Inspector
UnityEditor.Editor
, and apply the UnityEditor.CustomEditor
attribute to tell Unity that we want it to do the drawing for our component. OnInspectorGUI
method of the Editor
class. Leaving the method empty will result in an empty inspector as well. SerializedObject
instead of a single SerializedProperty
. Secondly, an instance of the editor exists as long as the object stays selected, keeping a reference to its data instead of getting it via a method parameter. Finally, we can use EditorGUILayout
, which takes care of positioning for us. We can get to the serialized object via the serializedObject
property. To prepare it for editing, we must first synchronize it with the component it represents, by calling its Update
method. Then we can show the properties. And after we are done, we have to commit any changes via its ApplyModifiedProperties
method. This also takes care of Unity's undo history. In between these two is where we'll draw our properties.
PropertyField
doesn't show any children – like array elements – unless we tell it to do so. Creating an Editor List
PropertyField
method. We will name this method Show and put it in its own static utility class, so we can use it wherever we want. We'll name this class EditorList and place it in the Editor folder. EditorGUILayout.PropertyField
without having it show the children of the list. Then we can show the list elements ourselves with help of the arraySize
property and the GetArrayElementAtIndex
method of SerializedProperty
. We'll leave the size for later. Properly Indenting
Unity Lists Api
ColorPointDrawer
behaves well. Collapsing Lists
isExpanded
property of our list. Showing the Size
Customizing the List
Using Flags
While we can keep adding options this way, our method calls will become increasingly obscure. We could add wrapper methods with more descriptive names, but that would bloat our script and isn't flexible. An alternative is the use of option flags. The first thing we need to do is create an enumeration of all our options. We name it EditorListOption and give it the System.Flags
attribute. We place it in its own script file or in the same script as EditorList
, but outside of the class.
|
. Show
method can now be replaced with a single options parameter. Then we'll extract the individual options with the help of the bitwise AND operator &
and store them in local variables to keep things clear. Hiding the Element Labels
Show
method is extract this option and perform a simple check. Let's also move the element loop to its own private method, for clarity. ColorPointDrawer
does not claim an extra line when it does not receive a label. Adding Buttons
Instead of removing parts, we can also add thing to our list. We could add a set of buttons for manipulating list elements. They can provide an alternative way to delete and duplicate elements, and we can add a means to reorder the elements as well.First we'll add an option for buttons, and also a convenient option to activate everything.
For the button labels we'll use a simple '+' for duplicate, a '-' for delete, and a '↴' (rightwards arrow with corner downwards) for move. You can directly insert the arrow unicode character, but I use its escape code just to be sure everyone can copy it correctly. We predefine static GUIContent
for these buttons and include handy tooltips as well. We also add a separate method for showing the buttons and call it after each element, if desired.
Unity Lists Api
EditorGUILayout.BeginHorizontal
and EditorGUILayout.EndHorizontal
. Fortunately, adding functionality to the buttons is very simple, as we can directly use the methods for array manipulation provided by SerializedProperty
. We need the list and the current element index for this to work, so we add them as parameters to our ShowButtons
method and pass them along inside the loop of ShowElements
.
While this is how Unity handles deletion in this case, it is weird. Instead, we want the element to always be removed, not sometimes cleared. We can enforce this by checking whether the list's size has remained the same after deleting the element. If so, it has only been cleared and we should delete it again, for real this time.
Only Allowing Lists
ListTester
that is not a list. Multi-object Editing
CanEditMultipleObjects
attribute to our ListTesterInspector
. Downloads
Unity List Add
- custom-list.unitypackage
- The finished project.