- Home /
Alternative to Unity's Standard GUI C#
Hi everyone, is there an alternative to Unity's standard GUI? Unity's GUI seems very inefficient. Like say I want to a large list of buttons and I want them to do something. I have to list all of those buttons individually and that results in a very inefficient and demanding script.Here is a example of what I mean
` using UnityEngine; using System.Collections;
public class ButtonInefficiency : MonoBehaviour {
public int Button1,Button2,Button3,Button4,Button5,Button6,Button7,Button8;
void OnGUI(){
if (GUI.Button(new Rect(525, 275, 25, 25), "Button1")){
++Button1;
}
if (GUI.Button(new Rect(525, 300, 25, 25), "Button2")){
++Button2;
}
if (GUI.Button(new Rect(525, 325, 25, 25), "Button3")){
++Button3;
}
if (GUI.Button(new Rect(525, 350, 25, 25), "Button4")){
++Button4;
}
if (GUI.Button(new Rect(525, 375, 25, 25), "Button5")){
++Button5;
}
if (GUI.Button(new Rect(525, 400, 25, 25), "Button6")){
++Button6;
}
if (GUI.Button(new Rect(525, 425, 25, 25), "Button7")){
++Button7;
}
if (GUI.Button(new Rect(525, 450, 25, 25), "Button8")){
++Button8;
}
//etc
}`
If I want to a large list of buttons I have to type the buttons, their positions and function for each button and that to me is inefficient and clunky.
Paste the code excerpt you feel is problematic, and we might be able to help you optimize it or at least clean it up aesthetically.
Unity standard GUI is a pain. UT is working on a new version and like @davea said, there are a bunch of options in the Asset Store.
Answer by DaveA · Sep 11, 2012 at 05:00 AM
There are a bunch of options in the Asset Store
That's not what I'm looking for. I'm looking for ways to be efficient with unity's GUI
Answer by Kaili-chan · Sep 11, 2012 at 11:41 PM
Well writing the same code over and over again reeks of poor coding habits and should be avoided to keep your code readable and maintainable. If you want to use Unity's Built in GUI system and you want to keep your code neat I would suggest a little of bit of code refactoring.
First I'd move your button creation code to a function that takes the items needed to create your button as parameters. Your function will take a rectangle of coordinates for the button. A string label, and an Action, that performs a function. You can read more about Actions here Action MSDN
private void Button(Rect r, String label, Action action) {
if(GUI.Button(r,label)) {
action();
}
}
You could either create a utility that will help you create GUIs by writing out their coordinates and label strings to a file then reading in said file at run time into an array. Or you could hardcode all your coordinates in an array and call them.
In my example I will read them from an array, how you created the array is just details and how you choose is up to how you feel comfortable.
Then from your OnGUI method you can call your Button method in a for loop and pass in the items you need.
public class ButtonDef {
Rect r;
String label;
Action action;
}
List<ButtonDef> buttons; // Populate this array
public void OnGUI() {
for(int i = 0; i < buttons.Length; i++) {
Button(buttons[i].r, buttons[i].label, buttons[i].action);
}
}
Make sure to define your Actions for each of your buttons. There are multiple approaches to solving this problem and I'll leave the finer parts of implementation up to the reader to figure out.
I'd highly recommend writing your own utility app in WinForms/WPF or if on a Mac in XCode to help you build a visual layout and write said layout to screen. That file can then be read in and parsed to create a ButtonDef. The action you will need to assign to a function for each of the buttons you create.
Implementation 2: The other approach you can use rather than an action is to keep a state machine where each button corresponds to a particular state. You then check said state at the end of every button creation loop and you can do your actions that way.
// Replace the action with some kind of enum state
enum State {
Options = 0,
MainMenu,
Resume,
None,
Count
};
private State buttonState = State.None;
public void OnGUI() {
for(int i = 0; i < buttons.Length; i++) {
Button(buttons[i].r, buttons[i].label, buttons[i].state);
}
ProcessButtonState();
}
public void ProcessButtonState() {
switch((int)buttonState) {
case (int)State.Resume: {do your processing here}
// Repeat for each state that you want to enumerate.
}
}
Again this is only a few ways you can write it but it should help clean up your code and make your programming tasks much easier.
Good hint.
I would suggest a little optimization. Since you created a class (ButtonRef), passing the instance to the method would be more efficient than extracting/copying its members:
private void Button(ButtonRef buttonRef)
Yeah there are lots of optimizations you can make to this code. I do like your way though :)
I'll leave it up the programmer to optimize their own code.
Answer by svenskefan · Sep 11, 2012 at 07:06 AM
Hi! First of all you have to define what you mean by efficient. If you mean nice-looking and neat, scriptwise, by all means: try to clean it up.
If you mean high performance, nice looking and using little resources, you would need to get some third party tool in the asset store.