- Home /
Naming array elements in editor
I'm setting up a system to spawn enemies in my game. Really this is just a cosmetic issue but I would just like to know how to set it up properly anyway.
I've created a new class that holds information about a round of enemy spawns, and then I'm using an array to store this information so that it appears in the editor like this:
What I want is instead of it saying "Element 0" I would prefer it to say "Wave 0" and then "Wave 1" etc. I know it's just a cosmetic thing but it's gonna bug me until I get it right :)
I found I could add a string variable to the class with the name "name" and whatever I changed that variable to would update the text "element 0" to be that name, but I would like it to just handle this automatically if possible.
Also if setting this all up in an array is the wrong way to go about it or you have any other suggestions please let me know!
Thank you!
Answer by Eric5h5 · Jul 18, 2011 at 04:31 PM
You can write a custom inspector, which duplicates the array functionality and adds the ability to change the element names. (By the way, it seems like a bug that having a string in the class changes the element name, especially since it only works if the string variable is first.)
Thanks! I wasn't aware you could do that and after looking it up it looks perfect.
If that's a bug I think we should just call it a feature...
I've found that using a 'name' property in custom classes is a handy way to make inspector values easier to read and/or more meaningful.
I can't agree; if I have an array in the inspector, I often prefer to know which element is which. If "Element 0", "Element 1", etc. are arbitrarily replaced by a string, that's usually not helpful to me. It's also inconsistent since it only happens if the first variable in the class is a string. If it's not a bug, it sure behaves like one.
I'll agree to disagree, but I've always found it more useful to see a meaningful label (that I choose) to represent elements in my arrays.
For example, if it was an array of weapons that my hero could choose from I'd rather see "Battle Axe" and "Flamethrower" than "Element 1" and "Element 5".
According to this forum post, it occurs whenever the first serializable member of a class is a string:
Not sure if that's true or not...
/tangent hijack
Answer by JGriffith · Jun 21, 2013 at 09:18 AM
I believe I have somewhat of an answer to your question. And this is way out of date but in case someone is looking I'll post and example here...
I have a simple container class that just holds the name of something and if it has been used or not:
[System.Serializable]
public class DragonsClass
{
public string Name;
[HideInInspector]
public bool bUsed;
}
public DragonsClass[] DragonsInLevel;
By filling out the name varaibles in the inspector, the "element#" is replaced by the string I enter:
No super useful for this example but you get the jist of an easy way to name your elements in the inspector.
I believe it uses the first property to display the name if that property is a string.
Answer by joaoborks · Mar 14, 2020 at 05:34 PM
If anyone else struggles with this, I've created a simple solution to name your array elements based on a given enum or array of strings:
Code Samples:
Attribute:
/**
* 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, label);
}
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;
}
Ah, I was able to get everything working! Although you may want to edit your example to use the Given GUILabel rather than the true value:
return EditorGUI.GetPropertyHeight(property, true);
Glad it worked for you! I will incorporate your suggestion that into my answer. Thanks for pointing that out.
I feel like an idiot, but I can't figure it out. I put the example in my script, and the editor script in the editor folder, but how do I decide which array I'm changing the names of?
It will only work on arrays that you explicitly set the attribute [LabeledArray]
. You will then have to use a string array for the names or an Enum as provided in the examples:
[LabeledArray(new string[] { "First", "Second", "Third" })]
public int[] labeledValues;
[LabeledArray(typeof(Order))]
public int[] enumLabeledValues;
Ohh, I got it working. I overlooked the fact that it was a customized attribute lol. I actually was not aware you could make those :P Thanks!