Linking event or custom callback for gui elements by using custom UI System

Hi there,

I am currently working with UnityGUI, and I found a problem, while I am used to add callbacks to buttons e.g. like in WinForms (onClick_button1(){do stuff}) I am kind of lost with Unity.

The problem is as you know Unity only draws GUI elements instead of creating a GUI element with data and draw it everytime.

My current work-around is called cUI (custom User Interface). This is a layer system which re-creates the UnityGUI system in a way in which we have more control about what element was clicked etc....

For example a cUI.Button is an object without any OnGUI method, it just contains information about a button that can be drawn. cUI is built of "Menues". A menue can contain any kind of cUI elements you pass in. Inside the menue all real GUI stuff is done, the menue has the OnGUI method which draws all the GUI elements you've passed into the current menue object. Plus it registers whether buttonA was pressed and puts this information into a queue, so we can keep track of which button / element was pressed. Plus it checks whether the element has a callback, if it has the menue calls the callback method by using `UnityEngine.Application.ExternalCall(string methodName, object[] parameters)` .

I didn't find a smarter way yet.

Any improvements or other ideas.

It sounds like you want a more object oriented, component based GUI system. That is exactly what we had to write as well for one of our projects. We defined classes for Button, TextField, Toggle, etc. This allowed team members for familiar with AS3, Swing, etc. for get up to speed quicker and gained us some efficiencies later on in the effort.

We used the build in C# event to implement OnClick, OnHover, OnDrag, Tooltip, etc. That way the effect of the button press (for instance) did not have to be inlined with the code in an if block. One thing I am not clear on in your post is the UnityEngine.Application.ExternalCall thing. That is only useful when you are in the web player and you are sending a message out of the web player runtime to the host environment (usually javascript in the page). If that's what you want I would decouple that and make a bridge that allows listening and registration for button clicks and delegates between the two instead of polluting your entire component model with that. The queue you speak of is already done for you in C# via the MulticastDelegate and event mechanism. Take a look here.

I think the biggest obstacle we ran into (other than the awkwardness of the GUI API itself) was keeping 'work' that was the result of the button presses out of the OnGUI thread. We ran into all sorts deadly embrace problems between Update and OnGUI. Make sure you only dispatch component events via the Update (in the Update method) pass. Store them in a temporary queue until the Update or FixedUpdate. If you don't, the execution path will spread through the OnGUI pass like a virus :-). You will wind up with all the work being done in the OnGUI thread which is bad. Performance will suck badly as one would expect.

Another issue was that you want to set up the components in the Awake method, but many times that means using the GUI class to set up styles and perform preliminary calculations which is not allowed. We found various ways to work around this,but never implemented an elegant solution... I have some ideas but I'm on a different project now.

I hope this helps, good luck on your project.