5
\$\begingroup\$

I have a member that I would like to expose:

[Serializable]
private sealed class InputGameObjectStack: Stack<GameObject> {
    public InputGameObjectStack(): base(_InputGameObjectStackSize) {
    }
}

Inside the MonoBehaviour, I have:

[SerializeField]
private InputGameObjectStack _inputGameObjectStack;

Inside the editor script, I'm able to fetch the property from the MonoBehaviour object (as SerializedProperty), but there is nothing usable that allows me to traverse through the elements.

Is there any way of showing the constents of the stack in the inspector as immutable (no functionality to push/pop)?

\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

Use CustomEditor to display the content of your stack

For Example

Assume we have the following class TestScript

TestScript

public class TestScript : MonoBehaviour {
    private Stack<GameObject> myStack = new Stack<GameObject>();
    void Start() {
        myStack.Push(new GameObject("Red Arrow"));
        myStack.Push(new GameObject("Green Ball"));
        myStack.Push(new GameObject("Blue Cake"));
    }
}

Create another class inside the existing class so it could access the private members, like so:



StackPreview added inside TestScript

public class TestScript : MonoBehaviour {
    private Stack<GameObject> myStack = new Stack<GameObject>();
    void Start() {
        myStack.Push(new GameObject("Red Arrow"));
        myStack.Push(new GameObject("Green Ball"));
        myStack.Push(new GameObject("Blue Cake"));
    }

    // This class is inside the TestClass so it could access its private fields
    // this custom editor will show up on any object with TestScript attached to it
    // you don't need (and can't) attach this class to a gameobject
    [CustomEditor(typeof(TestScript))]
    public class StackPreview : Editor {
        public override void OnInspectorGUI() {

            // get the target script as TestScript and get the stack from it
            var ts = (TestScript)target; 
            var stack = ts.myStack;

            // some styling for the header, this is optional
            var bold = new GUIStyle(); 
            bold.fontStyle = FontStyle.Bold; 
            GUILayout.Label("Items in my stack", bold);

            // add a label for each item, you can add more properties
            // you can even access components inside each item and display them
            // for example if every item had a sprite we could easily show it 
            foreach (var item in stack) {
                GUILayout.Label(item.name); 
            }
        }
    }
}

Now, in the editor you can see just the header (because we're adding items in the start function) - when you run the scene you get a nice list:

Result after running the scene

\$\endgroup\$
3
  • \$\begingroup\$ This is great, thank you! I thought about going with this route. But it didn't necessarily work since the field is private. \$\endgroup\$
    – mrkotfw
    Commented Feb 19, 2017 at 9:05
  • \$\begingroup\$ I have modified the code to support private fields as well. If this answer is acceptable, please mark it as Accepted. Thanks :-) \$\endgroup\$
    – lilotop
    Commented Feb 19, 2017 at 12:25
  • \$\begingroup\$ Thanks for the update. I guess there isn't any other way, other than to define the class inside. Messy, but it'll have to do. \$\endgroup\$
    – mrkotfw
    Commented Feb 20, 2017 at 10:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .