Search code examples
unity-game-engineunityscript

GUILayouts Aligning Problems


I'm trying to set up a highs-score indicator for a game and I want it to look the same for every device which is why I'm trying to use GUILayout. I'm still new to this and find this particular feature confusing. The General idea is to have a Layout that looks like this: High Score: (score), and in the game screen one that looks like this: (Coin Texture)x (amount collected). Any help on how to properly set this up would be amazing. Each one would go in the upper left corner of the screen.


Solution

  • GUILayout in Unity is more about automatic positioning and less about resolution independence. Essentially, GUILayout elements will be positioned automatically to the top-left corner of its containing area, and also sized automatically, unless you specify dimensions with GUILayoutOptions. Check out the GUILayout tutorial.

    To support all resolutions, you need to either use GUI.Matrix (explained here), or scale things manually using Screen.width and Screen.height.

    But resolution issues aside, here's some code to get you started (using the GUI.Matrix approach - the hard-coded pixel values will be relative to the chosen 1280x800 "native" layout resolution).

    public int currentScore = 120;
    public int highScore = 1490;
    public Texture2D coinTexture;
    
    // Native layout dimensions
    public const float LAYOUT_WIDTH = 1280f;
    public const float LAYOUT_HEIGHT = 800f;
    
    private void SetGUIMatrix()
    {
        Vector3 scale = new Vector3(Screen.width/LAYOUT_WIDTH,
                                    Screen.height/LAYOUT_HEIGHT,
                                    1f);
        GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, scale);
    }
    
    void OnGUI () 
    {
        SetGUIMatrix();
    
        Rect highScoreRect = new Rect(10, 10, 120, 100); // 120x100px rect near top left corner of the screen       
        GUILayout.BeginArea(highScoreRect);
        // High score
        GUILayout.Box("High score: " + highScore, new GUILayoutOption[] { GUILayout.Height(40) });
        // Current score
        GUILayout.BeginHorizontal();
        GUILayout.Box(coinTexture, new GUILayoutOption[] { GUILayout.Width(60), GUILayout.Height(40) });
        GUILayout.Box(currentScore.ToString(), new GUILayoutOption[] { GUILayout.Height(40) });
        GUILayout.EndHorizontal();      
        GUILayout.EndArea();
    }
    

    Note that with this approach, the elements will be stretched to accomodate different aspect ratios, this may or may not be what you want. Hope this helps!

    EDIT: Sorry, missed the JavaScript tag in the question. Here's the same in JS:

    var currentScore = 120;
    var highScore = 1490;
    var coinTexture : Texture2D;
    
    // Native layout dimensions
    var LAYOUT_WIDTH = 1280.0;
    var LAYOUT_HEIGHT = 800.0;
    
    function SetGUIMatrix()
    {
        var scale = new Vector3(Screen.width/LAYOUT_WIDTH,
                                Screen.height/LAYOUT_HEIGHT,
                                1.0);
        GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, scale);
    }
    
    function OnGUI () 
    {
        SetGUIMatrix();
    
        var highScoreRect = new Rect(10, 10, 120, 100); // 120x100px rect near top left corner of the screen        
        GUILayout.BeginArea(highScoreRect);
        // High score
        GUILayout.Box("High score: " + highScore, GUILayout.Height(40));
        // Current score
        GUILayout.BeginHorizontal();
        GUILayout.Box(coinTexture, GUILayout.Width(60), GUILayout.Height(40));
        GUILayout.Box(currentScore.ToString(), GUILayout.Height(40));
        GUILayout.EndHorizontal();      
        GUILayout.EndArea();
    }