External Modular UI Creation

Hey Forum,

I searched in the forum but didn’t found a proper answer to my problem and I am pretty new to Unity and C#.

I want to create a dynamic app-based UI in Unity. That means, a external script should be able to change the UIs behaviour, like e.g. adding a button in runtime or varying the location of a group of UI Elements.

In a first “test” I just want to have one script, with the Update() as my “runtime” and the OnGUI, where I receive the GUI-Objects from the Runtime.

To start simply, I tried to push the Objects directly into a Queue and handle them in the OnGUI(), but I got several Error MSG for trying to Call GUI Functions from outside the OnGUI().

How can I fix this? Or is there a much better solution?

public class IMGUI_Test : MonoBehaviour {

    int i;
    Queue myqueue = new Queue();

    // Use this for initialization
    void Start () {
        i = 5;
    }

    void OnGUI () {
        if (i > 500)
            i = 5;

        object actual = myqueue.Dequeue();

        i++;
    }
   
    // Update is called once per frame
    void Update () {

        myqueue.Enqueue(GUI.Button(new Rect(i, 10, 200, 20), "Click me!"));
   
    }
}

I haven’t done this myself, but I’ve seen scripts that call myGUI() functions from the Unity event OnGUI().

ex:

void OnGUI()
{
   classA1.myGUI();
   classA2.myGUI();
   ....
}

maybe have a List of class object refs and loop through them, call myGUI() on them? :]

Do you mean myGUI() as the myGUI library from OGRE? If so, I think it’s a little overpowered for my case :confused:

The GUI.Button doesn’t actually return a button object it returns a boolean that denotes if the button has been clicked or not.

The only way you can do what you describe is to write some wrapper classes that can draw “themselves”, you then enqueue these objects in the queue in update/whatever and then you call the drawing code in OnGUI.

public class IMGUI_Test : MonoBehaviour {
        Queue<ButtonWrapper> myqueue = new Queue<ButtonWrapper>();
        void OnGUI () {

            while (myqueue.Count > 0)
            {
                myqueue.Dequeue().Draw();
            }
        }
 
        // Update is called once per frame
        void Update () {
            myqueue.Enqueue(new ButtonWrapper("Click me!"));
        }

        private class ButtonWrapper
        {
            private string buttonText;

            public ButtonWrapper(string buttonText)
            {
                this.buttonText = buttonText;
            }

            public void Draw()
            {
                GUILayout.Button(buttonText);
            }
        }
    }

Obviously just some very simple example code, handling layout is going to be a pain though… I recommend that you check out the new UI-System (UGUI) as that is actually object based probably easier for you to work with. →

hey sindrijo,

Thanks for your reply, I worked my problem out with the wrapper classes and am in the testing now! Thanks for the tip :slight_smile: