x


How can I recreate the Array Inspector element for a custom Inspector GUI?

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: alt text

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[i];
            t = EditorGUILayout.ObjectField(t.name, t, typeof(Transform)) as Transform;
        }

        EditorGUILayout.EndVertical();
    }

}
more ▼

asked Aug 29 '10 at 11:23 PM

tylo gravatar image

tylo
297 5 9 18

your kinda vague, if your asking how to take a built in array with some array indexes empty, and resize it to not have those empty slots, i went through each index in your array(array A, looks like your using a built in array, idk i use JS), asked if its not empty (if !=null), then put it in another array (array B, i used a JS array), then make array A = array B(if JS array, A=B.ToBuiltin(var type(for you, Transform)).

please clarify your question if i have not already answered it.

Aug 30 '10 at 01:15 AM Techsuport
(comments are locked)
10|3000 characters needed characters left

3 answers: sort voted first

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));
    }
}
more ▼

answered Nov 16 '10 at 02:22 AM

Steven Walker gravatar image

Steven Walker
862 25 32 48

you made my day.. thanx!

Apr 01 '11 at 10:26 PM cupsster
(comments are locked)
10|3000 characters needed characters left

This is roughly what DrawDefaultInspector() does:

override def OnInspectorGUI():
    serializedObject.Update()

    EditorGUIUtility.LookLikeInspector()

    myIterator = serializedObject.FindProperty("myArrayField")
    while true:
        myRect = GUILayoutUtility.GetRect(0f, 16f);
        showChildren = EditorGUI.PropertyField(myRect, myIterator)
        break unless myIterator.NextVisible(showChildren)

    serializedObject.ApplyModifiedProperties()

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.

more ▼

answered Feb 24 '12 at 01:53 PM

steinbitglis gravatar image

steinbitglis
259 12 16 19

Thanks man! Almost the same as the default inspector! You saved my day. Now I need to figure out what each method does...

Dec 20 '12 at 07:23 AM mepine
(comments are locked)
10|3000 characters needed characters left

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
        // ...

    }
more ▼

answered Sep 24 '11 at 09:27 PM

Rafes gravatar image

Rafes
305 6 8 13

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x1664
x1356
x463
x347
x56

asked: Aug 29 '10 at 11:23 PM

Seen: 8131 times

Last Updated: Dec 20 '12 at 07:23 AM