Custom List, displaying Data yourIn this Unity C # tutorial You'll create a custom visualization for arrays and lists in the editor. You'll learn to create a custom editor with Serializedobject manipulate a serializedproperty that represents an array or List use a enumeration for option flags use GUI buttons
This tutorial comes after the Custom Data tutorial.
This tutorial are for Unity version 4.3 and above. The older version can still is found here. Inshare 1 Customized lists. Creating Test Data Unity's default-to-show lists is serviceable, but it's possible to find yourself wantingfor an alternative. The specifics can vary from case to case. So it would is useful if wecould use a mix of different visualizations. It's possible to does this by adding Attributesto variables that specify how the editor should show them.
We start with the finished Custom Data Tutorial project, or bycreating a new empty project and importing custom-data.unity Package.
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.
using Unityengine;
Public class Listtester : monobehaviour {public
int[] integers;
Public vector3[] vectors;
Public ColorPoint [] colorpoints;
Public Transform[] objects;
}
New test object, with wide inspector.
Creating a Custom InspectorOur first step to customizing we lists is to create a custom inspector for our test component. Create a new C # script named Listtesterinspector in the Editor folder, make Itextend unityeditor.editor, and apply the Uni Tyeditor.customeditorattribute to tell Unity, we want it to does the drawing for our component.
using Unityeditor;
using Unityengine;
[Customeditor (typeof(listtester))]
Public class Listtesterinspector : Editor {
}
Custom Inspector script. To actually change the inspector we need to override the Oninspectorgui method of the Editor class. Leaving the method empty would result in a empty inspector as well.
Public override void Oninspectorgui () {
}
Empty Inspector. There is three important differences between a property drawer and an editor. Firstly, in theeditor we work with an entire serializedobject instead of a single serializedproperty. Secondly, an instance of the editor exists as long as the objectstays selected, keeping a reference to its data instead of Getting it via a method parameter. Finally, we can use the editorguilayout, which takes care of the positioning for us.
We can get to the serialized object via the Serializedobject property. To prepare it-editing, we must first synchronize it with the Componentit represents, by calling its Update method. Then we can show the properties. And after we were done, we had tocommit any changes via its Applymodifiedproperties method. This also takes Careof Unity's undo history. In between these, where we'll draw our properties.
Public override void Oninspectorgui () {
serializedobject.update ();
Editorguilayout.propertyfield (Serializedobject.findproperty ("integers"));
Editorguilayout.propertyfield (Serializedobject.findproperty ("vectors"));
Editorguilayout.propertyfield (Serializedobject.findproperty ("colorpoints"));
Editorguilayout.propertyfield (Serializedobject.findproperty ("Objects"));
Serializedobject.applymodifiedproperties ();
}
Inspector with empty properties. The fields is visible again, but they ' re empty. This is because PROPERTYFIELDDOESN ' t show no children–like array elements–unless We tell it to does so.
Public override void Oninspectorgui () {
serializedobject.update ();
true);
true);
true);
true);
Serializedobject.applymodifiedproperties ();
}
Inspector with children.
Creating an Editor ListTo use a customized list in our inspector, we'll create an alternative for the Propertyfield method. We'll name this method Show and put it in the Itsown static utility class so we can use it wherever we want. We ' ll name this class editorlist and place it in the Editor folder.
using Unityeditor;
using Unityengine;
Public static Class Editorlist {public
static void Show (serializedproperty list) {
}
}
Editorlist script. This method doesn ' t does anything yet, but we can already with it in the custom editor, Resultingonce again in an empty Inspe ctor.
Public override void Oninspectorgui () {
serializedobject.update ();
editorlist. Show (Serializedobject.findproperty ("integers"));
editorlist. Show (Serializedobject.findproperty ("vectors"));
editorlist. Show (Serializedobject.findproperty ("colorpoints"));
editorlist. Show (Serializedobject.findproperty ("Objects"));
Serializedobject.applymodifiedproperties ();
}
Showing A list consists of three parts, its-foldout, its-size, and its-elements. We can show the foldout by using Editorguilayout.propertyfield without have itshow the children of the list. Then we can show the list elements ourselves with help's the ArraySize property and the Getarrayelementatindex method of Serializedproperty. We ' ll leave the size for later.
Public static void Show (Serializedproperty list) {
Editorguilayout.propertyfield (list);
for (int i = 0; i < list.arraysize; i++) {
Editorguilayout.propertyfield (list. Getarrayelementatindex (i));
}
}
Lists without indented elements.
properly indentingWe have a lists again, but their elements aren ' t indented. We can solve the increasingthe indent level before showing the elements, and decreasing it again afterwards.
Public static void Show (Serializedproperty list) {
Editorguilayout.propertyfield (list);
Editorgui.indentlevel + = 1;
for (int i = 0; i < list.arraysize; i++) {
Editorguilayout.propertyfield (list. Getarrayelementatindex (i));
}
Editorgui.indentlevel-= 1;
}
Messed up indenting. Now indentation works again, except for our color point list, which goes wrong after the firstelement. This is because we set the indent level to zero in our custom property drawer. There is the ways to fix this. Either our custom list should set the indent level to the Correctvalue again after each element, or the property drawer sh Ould Make sure it leaves the indent levelunchanged. Let's make sure that
Colorpointdrawerbehaves well.
Public override voidOngui (Rect position, Serializedproperty property, Guicontent label) {intOldindentlevel = Editorgui.indentlevel;
label = Editorgui.beginproperty (position, label, property); Rect contentposition = Editorgui.prefixlabel (position, label);if(Position.height > 16f)
{position.height = 16f;
Editorgui.indentlevel + = 1;
ContentPosition = Editorgui.indentedrect (position);
CONTENTPOSITION.Y + = 18f;
} contentposition.width *= 0.75f;
Editorgui.indentlevel = 0; Editorgui.propertyfield (ContentPosition, property.
Findpropertyrelative ("position"), Guicontent.none);
Contentposition.x + = Contentposition.width;
Contentposition.width/= 3f;
Editorguiutility.labelwidth = 14f; Editorgui.propertyfield (ContentPosition, property. Findpropertyrelative ("Color"),NewGuicontent ("C"));
Editorgui.endproperty ();
Editorgui.indentlevel = Oldindentlevel; }
Correct indenting, but no collapsing.
collapsing ListsNow this indenting works, we can take care of the next problem. Toggling the foldoutsshould collapse and expand the lists, but it currently doesn ' t work. This is an easy-to-fix bychecking the IsExpanded property of our list.
Public static void Show (Serializedproperty list) {
Editorguilayout.propertyfield (list);
Editorgui.indentlevel + = 1;
if (list.isexpanded) {for
(int i = 0; i < list.arraysize; i++) {
Editorguilayout.propertyfield (list. Getarrayelementatindex (i));
}
}
Editorgui.indentlevel-= 1;
}
correctly collapsing.
Showing the SizeTo show the list's size, we can use the special relative property named Array.size. We ' llsimply show it in between the foldout and the elements. Why isn't use arraySize here?
Public static void Show (Serializedproperty list) {
Editorguilayout.propertyfield (list);
Editorgui.indentlevel + = 1;
if (list.isexpanded) {
Editorguilayout.propertyfield (list. Findpropertyrelative ("Array.size"));
for (int i = 0; i < list.arraysize; i++) {
Editorguilayout.propertyfield (list. Getarrayelementatindex (i));
}
}
Editorgui.indentlevel-= 1;
}
Complete lists.
Customizing the ListNow, we have replicated the default list, it's time to add customizations. An easy startis to make the size that we just added optional. We Add a Boolean parameter to control Thisand turn it in by default. How does does showlistsize work?
Public static void BOOL true) {
Editorguilayout.propertyfield (list);
Editorgui.indentlevel + = 1;
if (list.isexpanded) {
if (showlistsize) {
Editorguilayout.propertyfield (list. Findpropertyrelative ("Array.size"));
}
for (int i = 0; i < list.arraysize; i++) {
Editorguilayout.propertyfield (list. Getarrayelementatindex (i));
}
}
Editorgui.indentlevel-= 1;
}
Using This new option, we can switch to the size of some of our lists.
Public override void Oninspectorgui () {
serializedobject.update ();
editorlist. Show (Serializedobject.findproperty ("integers"));
editorlist. Show (Serializedobject.findproperty ("vectors"));
editorlist false);
editorlist false);
Serializedobject.applymodifiedproperties ();
}
Hiding some of the list sizes. As a second option, let's make the list's label optional as well. If we don ' t show the Label,we won ' t indent either and we'll always show the elements, regardless whether the list Isexpa nded.
Public static void BOOL true BOOL true) {
if (showlistlabel) {
Editorguilayout.propertyfield (list);
Editorgui.indentlevel + = 1;
}
if (!showlistlabel | | list.isexpanded) {
if (showlistsize) {
Editorguilayout.propertyfield (list. Findpropertyrelative ("Array.size"));
}
for (int i = 0; i < list.arraysize; i++) {
Editorguilayout.propertyfield (list. Getarrayelementatindex (i));
}
}
if (Showlistlabel) {
Editorgui.indentlevel-= 1;
}
}
Now we can remove the label from some for our lists.
Public override void Oninspectorgui () {
serializedobject.update ();
editorlist true false);
editorlist. Show (Serializedobject.findproperty ("vectors"));
editorlist false false);
editorlist false);
Serializedobject.applymodifiedproperties ();
}
Hiding some of the list labels.
Using FlagsWhile we can keep adding options the This is, our method calls would become increasingly obscure. We could add wrapper methods with more descriptive names, but that would bloat our script Andisn ' t flexible. An alternative are the use of the option flags.
The first thing we need to does is create a enumeration of all our options. We name Iteditorlistoption and give it the System.flags attribute. We place it in Itsown script file or in the same script as Editorlist, but outside of the class. is the Flags attribute required?
using Unityeditor;
using Unityengine;
using System;
[Flags]
Public enum Editorlistoption {
}
Now we add entries for the and the options that we already has. We also add an option to when wewant nothing and for when we want the default. The default is to show both the list ' s label andits size. We specify the combining both options with the bitwise OR operator |. How does bitwise flags work?
[Flags]
Public enum Editorlistoption {
None = 0,
listsize = 1,
Listlabel = 2,
Default = Listsize | Listlabel
}
The Boolean parameters of the Show method can now is replaced with a single optionsparameter. Then we ' ll extract the individual option