The Array handling in the editor is really poor.
I have been looking for a better way to use arrays adding button to insert delete or move elements.
Thanks to Naked Chicken who post a way to move string arrays using in this post : Tired of the limited viewing capabilities of strings in your inspector?
I’ve then tried to make a generic script that should work with almost any type of field. And the result is quite simple :
It works with primitives and with Classes !!!
First adds a class ArrayAttribute.cs :
using UnityEngine;
using System.Collections;
public class ArrayAttribute : PropertyAttribute
{}
and a Property drawer inside an Editor folder
using UnityEngine;
using System.Collections;
using UnityEditor;
// The property drawer class should be placed in an editor script, inside a folder called Editor.
// Tell the ArrayDrawer that it is a drawer for properties with the ArrayAttribute.
[CustomPropertyDrawer(typeof(ArrayAttribute))]
public class ArrayDrawer : PropertyDrawer
{
const float widthBt = 35;
void addArrayTools(Rect position, SerializedProperty property)
{
string path = property.propertyPath;
int arrayInd = path.LastIndexOf(".Array");
bool bIsArray = arrayInd >= 0;
if (bIsArray)
{
SerializedObject so = property.serializedObject;
string arrayPath = path.Substring(0, arrayInd);
SerializedProperty arrayProp = so.FindProperty(arrayPath);
//Next we need to grab the index from the path string
int indStart = path.IndexOf("[") + 1;
int indEnd = path.IndexOf("]");
string indString = path.Substring(indStart, indEnd - indStart);
int myIndex = int.Parse(indString);
Rect rcButton = position;
rcButton.height = EditorGUIUtility.singleLineHeight;
rcButton.x = position.xMax - widthBt * 4;
rcButton.width = widthBt;
bool lastEnabled = GUI.enabled;
if (myIndex == 0)
GUI.enabled = false;
if (GUI.Button(rcButton, "Up"))
{
arrayProp.MoveArrayElement(myIndex, myIndex - 1);
so.ApplyModifiedProperties();
}
rcButton.x += widthBt;
GUI.enabled = lastEnabled;
if (myIndex >= arrayProp.arraySize - 1)
GUI.enabled = false;
if (GUI.Button(rcButton, "Dn"))
{
arrayProp.MoveArrayElement(myIndex, myIndex + 1);
so.ApplyModifiedProperties();
}
GUI.enabled = lastEnabled;
rcButton.x += widthBt;
if (GUI.Button(rcButton, "Del"))
{
arrayProp.DeleteArrayElementAtIndex(myIndex);
so.ApplyModifiedProperties();
}
rcButton.x += widthBt;
if (GUI.Button(rcButton, "Ins"))
{
arrayProp.InsertArrayElementAtIndex(myIndex);
so.ApplyModifiedProperties();
}
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
addArrayTools(position, property);
Rect rc = position;
if (!property.isExpanded)
rc.width -= widthBt * 4;
EditorGUI.PropertyField(rc, property, label, true);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property);
}
}
Then in your own MonoBehavior adds a attribute class [Array]
example :
[Array]
public MyClass[] theArray;
[Array]
public int[] theIntArray;
I’ve added a unity package containing the 2 main classes and an example
I hope It could help.
1595948–95982–$ArrayPropertyAttribute.unitypackage (2.96 KB)