I’ve been looking and googling for a way to do that for hours now… is there really no attribute or something to do this simple thing - provide a string to be used in place of the variable name (or Element 0, 1…)?
Do I really need to write some custom attribute and drawer-thingy for this?
Forget drawers and attributes - you just need to write a custom inspector class for your script - it only takes a couple of lines, and you get a lot of flexibility as a result:
If the first variable in the class is a string, then Unity will use that variable as the array item label.
I’ve found other sources that say the variable needs to be named title, name, or key, but it doesn’t seem to matter anymore:
// Here, Funky is used as the array item label. Title and ToString are ignored.
[Serializable]
public class Pairs {
public string Funky;
public string Title;
public bool IsMeshVisible;
public string ToString()
{
return string.Format("{0} {1}", Funky, IsMeshVisible);
}
}
/**
* LabeledArrayAttribute.cs
* Created by: Joao Borks [joao.borks@gmail.com]
* Created on: 28/12/17 (dd/mm/yy)
* Reference from John Avery: https://forum.unity.com/threads/how-to-change-the-name-of-list-elements-in-the-inspector.448910/
*/
using UnityEngine;
using System;
public class LabeledArrayAttribute : PropertyAttribute
{
public readonly string[] names;
public LabeledArrayAttribute(string[] names) { this.names = names; }
public LabeledArrayAttribute(Type enumType) { names = Enum.GetNames(enumType); }
}
Property Drawer:
/**
* LabeledArrayDrawer.cs
* Created by: Joao Borks [joao.borks@gmail.com]
* Created on: 28/12/17 (dd/mm/yy)
* Reference from John Avery: https://forum.unity.com/threads/how-to-change-the-name-of-list-elements-in-the-inspector.448910/
*/
using UnityEngine;
using UnityEditor;
using System.Linq;
// Don't forget to put this file inside an Editor folder!
[CustomPropertyDrawer(typeof(LabeledArrayAttribute))]
public class LabeledArrayDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, true);
}
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(rect, label, property);
try
{
var path = property.propertyPath;
int pos = int.Parse(path.Split('[').LastOrDefault().TrimEnd(']'));
EditorGUI.PropertyField(rect, property, new GUIContent(((LabeledArrayAttribute)attribute).names[pos]), true);
}
catch
{
EditorGUI.PropertyField(rect, property, label, true);
}
EditorGUI.EndProperty();
}
}
Example:
using UnityEngine;
public class LabeledArrayExample : MonoBehaviour
{
[LabeledArray(new string[] { "First", "Second", "Third" })]
public int[] labeledValues;
public enum Order
{
First,
Second,
Third
}
[LabeledArray(typeof(Order))]
public int[] enumLabeledValues;
}