I've been running into troubles doing this and could use some extra thoughts. Here is the code I have so far.
I have an array stored in a script component named `Enemy`. I access this script component, and display it in my custom Inspector, but I always receive errors that not all elements are initialized.
Essentially, I am getting hung up on the idea of how this works:
How can I get `None (Transform)` to appear in my Inspector instead of an error?
private bool collapsed;
private int arraySize;
private Enemy e;
public override void OnInspectorGUI()
{
EditorGUIUtility.LookLikeControls();
e = target as Enemy;
collapsed = EditorGUILayout.Foldout(collapsed, "Array");
if (collapsed)
{
Rect r = EditorGUILayout.BeginVertical();
arraySize = EditorGUILayout.IntField
if (e.array.Length > 0)
{
Transform[] temp = new Transform[arraySize];
e.array.CopyTo(temp, 0);
e.array = new Transform[arraySize];
temp.CopyTo(e.array, 0);
}
else
e.array = new Transform[arraySize];
for (int i = 0; i < arraySize; i++)
{
Transform t = e.array*;*
*t = EditorGUILayout.ObjectField(t.name, t, typeof(Transform)) as Transform;*
*}*
*EditorGUILayout.EndVertical();*
*}*
*}*
*```*
For anyone else who is searching for the solution to this, here is working code in Javascript. It doesn't look the same as the built-in array controls, but it works fine.
// MyObject.js
public var ElementsExpand : boolean = true;
public var ElementsSize : int = 1;
public var Elements : Transform[] = new Transform[ElementsSize];
// MyObjectEditor.js - OnInspectorGUI()
target.ElementsExpand = EditorGUILayout.Foldout(target.ElementsExpand, "Transforms");
if(target.ElementsExpand) {
var x : int = 0;
target.ElementsSize = EditorGUILayout.IntField("Size", target.ElementsSize);
if(target.Elements.length != target.ElementsSize) {
var newArray : Transform[] = new Transform[target.ElementsSize];
for(x = 0; x < target.ElementsSize; x++) {
if(target.Elements.length > x) {
newArray[x] = target.Elements[x];
}
}
target.Elements = newArray;
}
for(x = 0; x < target.Elements.length; x++) {
target.Elements[x] = EditorGUILayout.ObjectField("Element "+x, target.Elements[x], typeof(Transform));
}
}
It works like it should with bold font on prefab overrides etc. It also handles undo operations, ‘delete’ operations and ‘shift+delete’ operations as expected. It works with all the kinds of arrays that Unity originally supports. It also looks like the original.
Remember to call EditorGUIUtility.LookLikeControls() after drawing the array.
To expand on what @Steven Walker posted, Started down this road using the newer List<>. I found that typing things like “-” or leaving a field empty destroys the list (counts as “0” elements), so I wrote this code snip-it in C#. This is just for reference, not a complete solution. I decided it would be more user-friendly to supply +/- buttons per element so things can be inserted or removed. I always hated the default method of just destroying from the end. I might even add up and down buttons just for pure organization use…
Anyway. Here is some code which uses a text field and only changes the size value if an actual number is entered. Also note that this clamps to 0-9 since typing 10 would type a “1” first and destroy the list down to 1 item.
private string entry;
public override void OnInspectorGUI()
{
var script = (FireController)target;
...
// Use a string entry so we can ignore special situations like a "-" or
// Empty field until an actual number is typed.
this.entry = EditorGUILayout.TextField("Size", this.entry);
// TryParse will set it if it can and never throw an error.
int size;
bool result = System.Int32.TryParse(entry, out size);
// Protect against typing out of a reasonable range
// Can't allow "10" because it would be read as "1" first!
size = Mathf.Clamp(size, 0, 9);
// If the user changed the count, add or remove elements
while (size != script.myList.Count)
{
if (size > script._effectsOnTarget.Count)
script._effectsOnTarget.Add(new MyTYPE());
else
script._effectsOnTarget.RemoveAt(script.myList.Count-1);
}
// No go through the list and add the EditorGUILayout items
// ...
}