Unity3D: Auto Scale GUI

As this is my very first post on anything Unity3D related, I thought I would share this: The single, most powerful bit of code that I use. Every day. It’s not really that complicated, but before I discovered it coding for Unity’s GUI was a bit less pleasant.

What I’m referring to is a little tidbit that scales the entire GUI based on the resolution that the graphics were authored at. So without further ado..

C#

1
2
3
4
5
public static void AutoResize(int screenWidth, int screenHeight)
{
    Vector2 resizeRatio = new Vector2((float)Screen.width / screenWidth, (float)Screen.height / screenHeight);
    GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(resizeRatio.x, resizeRatio.y, 1.0f));
}

Javascript

1
2
3
4
5
public static function AutoResize(screenWidth:int, screenHeight:int):void
{
    var resizeRatio:Vector2 = Vector2(Screen.width / parseFloat(screenWidth), Screen.height / parseFloat(screenHeight));
    GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3(resizeRatio.x, resizeRatio.y, 1.0));
}
What we do here is:
  1. Figure out the ratio of our current screen resolution compared to our authored resolution
  2. Set our current GUI transform matrix to a scaled one

Not too much too it right? Doing this allows you to use absolute sizes and positions when you are drawing your buttons, labels, textures etc. in the GUI. They will automatically scale up or down depending on your resolution.

Note: Using this approach you will want to avoid using Screen.width or Screen.height for sizes & positions to avoid double scaling.

AutoResize Function

AutoResize  is public and static so we can define it once, and call it from anywhere. The function takes 2 parameters:

public static void AutoResize(int screenWidth, int screenHeight)
  • screenWidth: the authored width of the game
  • screenHeight: the authored height of the game

By authored resolution, I am referring to the resolution you intend the graphics to be viewed at.

For example: If I call AutoResize(1920, 1080), when I view the game at 1920×1080 resolution in full screen, my graphics will look 1 to 1 how they were created. If I view the game at any other 16:9 resolution, the graphics will scale up or down in size. At any other resolution however, say 1920×1200, the graphics will stretch as well as scale.

C#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using UnityEngine;

public class ScaleGUI : MonoBehaviour
{
    public Texture2D Image;

    void OnGUI()
    {
        AutoResize(1920, 1200);

        GUI.DrawTexture(new Rect(0.0f, 0.0f, Image.width, Image.height), Image);
    }

    public static void AutoResize(int screenWidth, int screenHeight)
    {
        Vector2 resizeRatio = new Vector2((float)Screen.width / screenWidth, (float)Screen.height / screenHeight);
        GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(resizeRatio.x, resizeRatio.y, 1.0f));
    }
}

Here we create a simple C# class. We call AutoResize() first in OnGUI . What this does is scale everything after it this draw call within OnGUI. Important: AutoResize() must be called on every GameObject that would have any GUI content scaled. 

Image now gets scaled on the screen according to how our actual resolution compares to the authored resolution.

GetResizedRect Function

As a bonus I’ll throw in this function which allows you to scale a single rectangle. You could also use it to figure out what Rectangles you are actually drawing, in case you need to test a Rect Contains() in the Update function or something.

C#

1
2
3
4
5
6
7
public static Rect GetResizedRect(Rect rect)
{
    Vector2 position = GUI.matrix.MultiplyVector(new Vector2(rect.x, rect.y));
    Vector2 size = GUI.matrix.MultiplyVector(new Vector2(rect.width, rect.height));
   
    return new Rect(position.x, position.y, size.x, size.y);
}
Concluding..

This is perhaps the most useful when mirroring a Standalone build in the Web Player. Most web builds are quite a bit smaller than a high res desktop build, and graphics that don’t scale down can get pushed right off the screen!

Be sure to make sure though that this technique suits your project before relying on it. When I am coding a project, typically it is GUI heavy and the target client’s resolution is not going to change. This technique is very convenient for this situation. If, however, your project targets a wide range of resolutions, this may not be the best technique to implement, as a portion of your users would have stretched graphics and be using textures much larger than necessary for their screen.

Enjoy!

Ben

10 thoughts on “Unity3D: Auto Scale GUI

  1. Toby

    Awesome man! Thanks so much for this. I’ve been looking forever for something as simple and easy to understand as your explanation!

    Thanks!

  2. Boreale

    Wow thank you man! This definitely should be in GUI.matrix page on unity scripting reference!

  3. Zongo

    Thanks a lot man! This tut is awesome because takes care about who script in C# and in javascript both!

Leave a Reply

Your email address will not be published. Required fields are marked *