Tuesday, November 02, 2010

Automagic GUI Scaling in Unity3D

Step 1. Tell you team that everything must fit within 1920x1080 or 1024x768 or whatever resolution you like!

Step 2. Surround all OnGUI method body code with methods BeginGUI and EndGUI from the below class.

Step 3. Scaling across all resolutions... problem solved!

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GUISizer {

static float WIDTH = 1024;
static float HEIGHT = 768;

static List<Matrix4x4> stack = new List<Matrix4x4> ();

static public void BeginGUI() {
stack.Add (GUI.matrix);
Matrix4x4 m = new Matrix4x4 ();
var w = (float)Screen.width;
var h = (float)Screen.height;
var aspect = w / h;
var scale = 1f;
var offset = Vector3.zero;
if(aspect < (WIDTH/HEIGHT)) { //screen is taller
scale = (Screen.width/WIDTH);
offset.y += (Screen.height-(HEIGHT*scale))*0.5f;

} else { // screen is wider
scale = (Screen.height/HEIGHT);
offset.x += (Screen.width-(WIDTH*scale))*0.5f;
}
m.SetTRS(offset,Quaternion.identity,Vector3.one*scale);
GUI.matrix *= m;
}

static public void EndGUI() {
GUI.matrix = stack[stack.Count - 1];
stack.RemoveAt (stack.Count - 1);
}

}

11 comments:

Anonymous said...

awesome automagic, it works great! thanks!

Anonymous said...

Sorry, i m a noob,
I make a "GUIMatrixSaler.cs" and fill in your script. Now it in the Asset folder and i give it to an GuiTexture. But if i type in "GuiMatrixScaler.BeginGUI();"
the compiler said Unknown identifier.
Please can you explain me how to handle this?
thanks a lot

Simon Wittber said...

The filename needs to be the same as the class name, so try renaming the file to GUISizer.cs and it should work.

Anonymous said...

Assets/GUISizer.cs(9,14): error CS1519: Unexpected symbol `static' in class, struct, or interface member declaration

Anonymous said...

Thanks this was very helpful!

Robin Bonhoure said...

Hey thanks for your script, very usefull.

I just have an issue.
The "GUIUtility.RotateAroundPivot" doesn't work well after a resize, do you know a solution ?

Thanks

Anonymous said...

Thank you very much! The script saved me a lot of time

Anonymous said...

I love this, thank you so much.

Meanest Man in England (Previously America) said...

Hi,

I have implemented this GUISizer and it works very well with one exception and I would like to get your thoughts on it?

The exception is when I try to display a GUI Box with an x, y derived from Camera.main.WorldToScreenPoint. If I run the game with screen Maximise on Play everything is fine however, if I run with out it, the GUI Box is way off screen in the middle of nowhere. I would appreciate any insight?

Regards,

Gary

Virgilia said...

The code is unfortunately not optimized at all. Creating new temporary variables and recalculating the matrix every time BeginGUI is called (multiple times per frame per script that uses it), as well as your unnecessary stack array whose size gets increased and causes crashes due to memory usage.
Just in case anyone needs a more optimized version of the script:
-Changed BeginGUI to BeginGUI(width,height) for more flexibility.
-Made the matrix calculations only occur at the beginning, and when the resolution changes.
-Removed the stack thing.
http://pastebin.com/RZByVEVT

Simon Wittber said...

@Virgilia this is just a demonstration, in my own library I use something similar to what you have described.

The stack will not grow forever if you call make matching BeginGUI and EndGUI calls.

Also all the variables in the method are value types which come from the stack, and are not allocated.

Popular Posts