Fully Responsive User Interface with Unity GUI

August 12th, 2013

IMPORTANT: It was brought to my attention that the newer versions of Unity have broken my little framework. Be advised, it was intended for the 4.* version of the engine. The new inbuilt GUI in Unity accomplishes the task nicely, and, if you’re using 4.6, 5.0 or a later version of the engine, you should go with the inbuilt tools, which are more efficient, reliant and versatile.

Unity GUI gets a lot of criticism, and there are reasons for that: it’s not visual at all, you have to code everything, most of the time you can’t use it on mobile due to high redraw frequency and excessive drawcall use, etc. I agree with all that. However, it has a number of important advantages as well: unlike most of the external libraries and plugins from the Asset Store, it is integrated into the engine really well, and it is completely free. You can’t say that about EZ GUI or NGUI, now can you? This last reason is probably the main thing that makes people use Unity GUI, and they are right to do so. Why pay $100+ when you can get the same result for free?

I have used Unity GUI on a variety of different projects and in a variety of situations. Over the years I have dug up a bunch of really useful tricks that help me code a basic interface in a matter of minutes. It was a couple of weeks ago that I decided to gather this stuff in one class that helps me overcome the main bottleneck of Unity GUI: its inherent lack of responsiveness. The term “responsive” comes from web design, and means that the interface adapts to the screen resolution. A modest example of responsive web design is my web site. Try resizing the window of your browser and see how everything scales and moves around. When you are making a cross-platform or PC game, you want it to be able to adapt to resolution as well, and to do that, the interface elements have to stick to their part of the screen and retain their size relative to the screen size.

My class is based on the basic idea behind Automagic GUI Scaling in Unity3D by Simon Wittber: you choose one resolution that you consider the “base” resolution, defined as WIDTH and HEIGHT constants in the beginning of the script (usually it will be the most popular resolution of your intended audience), then resize the GUI elements using GUI.matrix. The difference is that in Simon’s example you will end up with “offsets” on top and bottom of the screen if your screen ratio is different from the resolution that you specified with WIDTH and HEIGHT, which we don’t want. I solve this problem by applying the resize method to different regions of the screen separately, thus effectively masking the annoying offsets.

Now that we’re done with theory and explanations, you can get the GUISizer class here:http://goo.gl/wgdFX6. You can also download an example project here: http://goo.gl/5F5PIY. Or, if you prefer, the same thing as a UnityPackage that you can import into your own project: http://goo.gl/GKczDm. The source code is also added to the bottom of this post in case the links die. If you use C#, then feel free to put GUISizer.cs anywhere you want in your project. However, if UnityScript is your cup of tea, then it has to go into your Plugins folder. Otherwise you won’t be able to access its methods and structures.

With that out of the way, you can start poking around in the test project. To test how it works, just try resizing your Game view window. Below is some API with explanations, as well as the source code. Feel free to ask questions or suggest adding or changing things in the comments or elsewhere. You can use GUISizer in any commercial or noncommercial projects as you see fit. And of course enjoy the fully resizable Unity GUI!

P.S. As a bonus track, in the example project you will find a script that lets you position a GUI element in world coordinates (like the text label that you can see sticking to the cube in the video above).

Struct:

struct GUIParams

This struct lets you create a variable of type GUIParams: a button or a label, with specific parameters that you pass to the constructor.

Draws a specific label. Takes a GUIParams struct as a parameter. You can also provide a custom style and a custom font size as a parameter. Additionally, you can provide text that will be appended to the label, which is useful for things like score and lives.

Variables:

float WIDTH = 960;

The “base” width of the screen. This is the width of the screen relative to which all GUI elements will be resized. Change it directly in GUISizer script.

float HEIGHT = 600;

The “base” height of the screen. This is the height of the screen relative to which all GUI elements will be resized. Change it directly in GUISizer script.

I totally agree with your post. Even on Mobile you can get a decently performing GUI if you are applying some calculations and avoid using GUILayout class (disabling it)

However, recent requirement to draw 3D objects on top of GUI forced me to use a GUI frameworks like NGUI since you cannot do that with OnGUI

http://sergeymohov.com/ Sergey Mohov

Yeah, I didn’t use GUILayout in my GUISizer class on purpose, as I’m aware of the drawbacks.

And yes, drawing 3D objects on top of GUI is impossible indeed, which, if you ask me, is a flaw in Unity’s rendering pipeline. A camera drawn after another camera should always be on top, GUI or no GUI. Oh well.

Miu

Hey thanks for this post, but the link sources seems to be broken? can you update them ? pretty please? thanks

http://sergeymohov.com/ Sergey Mohov

Hi! Sorry, I had no idea, it’s been a while since I tested this. I’ll see what I can do and post another comment here if I update the source.