Search Unity

How-to-make-GUI-Buttons-on-GUI-Texture-resolution-independent

Discussion in 'Immediate Mode GUI (IMGUI)' started by Exnihilon, Apr 13, 2014.

  1. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    158
    Hello everyone. I am newbie to Unity and Android developent, and I am in need of your help to make my GUI controls resolution independent. I have posted the same question on the Android development forum (GUI and Android dev), but I got not responce, so I am posting here with code, for better.

    I have a GUITexture in my scene to be used as a graphical background for a controller, and above this, a set of GUI buttons is rendered in absolute x,y screen positions. Those two elements rendered together makes the buttons controller for my android application, in a 480x320 HVGA Landscape screen resolution(see image 1):

    $GUITexturenButtons.jpg

    The problem is that if the resolution is changed to 800x480 WVGA Landscape, everything is meshed up as you can see in the following screenshot:

    $ScatterGUIandButtons.jpg

    I have tryed to make use of the Matrix4x4 to keep the GUI buttons scaled to a new resolution, but I still get them scattered all around screen.

    Could anyone be kind enough to give some advise or maybe a code snippet on how to make both GUI buttons on absolute possitions and GUI Texture, screen resolution independent?

    These is the script for rendering the GUIButtons above GUITexture:

    Code (csharp):
    1.     using UnityEngine;
    2.     using System.Collections;
    3.      
    4.     public class GUIButtons : MonoBehaviour {
    5.      
    6.     public Texture btnTexture1;
    7.     public Texture btnTexture2;
    8.     public Texture btnTexture3;
    9.     public Texture btnTexture4;
    10.     public Texture btnTexture5;
    11.     public Texture btnTexture6;
    12.     public Texture btnTexture7;
    13.     public Texture btnTexture8;
    14.      
    15.      
    16.     void OnGUI()
    17.     {
    18.      
    19.     if (!btnTexture1) {
    20.     Debug.LogError("Please assign a texture on the inspector");
    21.     return;
    22.     }
    23.     GUI.Button(new Rect(68, 219, 50, 35), "");
    24.      
    25.     if (!btnTexture2) {
    26.     Debug.LogError("Please assign a texture on the inspector");
    27.     return;
    28.     }
    29.      
    30.     GUI.Button(new Rect(130, 219, 50, 35), "");
    31.      
    32.     if (!btnTexture3) {
    33.     Debug.LogError("Please assign a texture on the inspector");
    34.     return;
    35.     }
    36.     GUI.Button(new Rect(68,262,50,35), "");
    37.      
    38.     if (!btnTexture4) {
    39.     Debug.LogError("Please assign a texture on the inspector");
    40.     return;
    41.     }
    42.     GUI.Button(new Rect(305, 219, 50, 35), "");
    43.      
    44.     if (!btnTexture5) {
    45.     Debug.LogError("Please assign a texture on the inspector");
    46.     return;
    47.     }
    48.     GUI.RepeatButton(new Rect(366, 219, 50, 35), "");
    49.      
    50.      
    51.     if (!btnTexture6) {
    52.     Debug.LogError("Please assign a texture on the inspector");
    53.     return;
    54.     }
    55.     GUI.RepeatButton(new Rect(130,262,50,35), "");
    56.      
    57.     if (!btnTexture7) {
    58.     Debug.LogError("Please assign a texture on the inspector");
    59.     return;
    60.     }
    61.     GUI.Button(new Rect(305, 262, 50, 35), "");
    62.      
    63.     if (!btnTexture8) {
    64.     Debug.LogError("Please assign a texture on the inspector");
    65.     return;
    66.     }
    67.     GUI.RepeatButton(new Rect(366, 262, 50, 35), "");
    68.      
    69.     }
    70.     }
    Thank you all in advance for your answers.
     
  2. Blaveloper

    Blaveloper

    Joined:
    Nov 22, 2012
    Posts:
    46
    It requires a bit of mathematics for this issue.
    You want to do it for the horizontal part?

    Code (csharp):
    1. void OnGUI() {
    2.     // Formula to centre the button on the x-axis, no matter the resolution nor aspect ratio.
    3.     float centred = browserWidth/2;
    4.  
    5.     // Create the button. Note how I use another formula for the 'left' placement.
    6.     GUI.Button(new Rect(Screen.width/2-centred, 50, browserWidth, browserHeight), "Web browser");
    7. }
    If you want to use it for the vertical part, simply re-use the same formula for the height.
    Want to use both? Simply make a second formula for the centring.

    Edit:
    Just using "Screen.width" and "Screen.height" will put the button just out of the screen, make sure you position it by subtracting it.
    For example: Screen.height-100
    This will put the button 100 pixels above the bottom of the screen.
     
    Last edited: Apr 13, 2014
  3. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    158
    Hello Blaveloper, thank you for your answer. Yes I want to use the left landscape (horizontal) orientation on the Android device.
    Should I use your code snippet OnGUI or before creating every single button?
    May I ask another question to you? Can you post a snippet code on how to call a script when touching GUITexture?
    I have a script "Script A', attached to a GameObject "Cube" and I want to run "Script A" when I touch the GUITexure Button "Button".
    I believe I should be using GetComponent fuction but I am novice in Unity and I could not get it done right. Thanks again.
     
    Last edited: Apr 13, 2014
  4. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    158
    Well Blaveloper, I have tried your snippet code and I get this error : "Error CS0103: The name `browserWidth' does not exist in the current context'. Why is this happening? Should I mention that my coding is in C#. Here is a section of my code:

    Code (csharp):
    1.  
    2. using System.Collections;
    3.  
    4. public class GUIButtons : MonoBehaviour {
    5.    
    6.     public Texture btnTexture1;
    7.     public Texture btnTexture2;
    8.     public Texture btnTexture3;
    9.     public Texture btnTexture4;
    10.     public Texture btnTexture5;
    11.     public Texture btnTexture6;
    12.     public Texture btnTexture7;
    13.     public Texture btnTexture8;
    14.  
    15.     //Draws GUI elements
    16.           void OnGUI()
    17.     {
    18.        
    19.  
    20.            
    21.                if (!btnTexture1) {
    22.            
    23.             Debug.LogError("Please assign a texture on the inspector");
    24.             return;
    25.                
    26.         // Formula to centre the button on the x-axis, no matter the resolution nor aspect ratio.
    27.         float centred = browserWidth/2;
    28.      
    29.         // Create the button. Note how I use another formula for the 'left' placement.
    30.         GUI.Button(new Rect(Screen.width/2-centred, 50, browserWidth, browserHeight), "");
    31.     }
    32.  
     
  5. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    It's a field, set/declare them as a value. Also,your missing a closing bracket for the "if" statement.
     
    Last edited: Apr 13, 2014
  6. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    158
    Thanks Iandon91235 for your sharp eye! I have declared the fields but on game preview I get nothing, meaning I still not get the GUIButtons repositioned as they were on 480x320 px screen, in 800x480 px. Is it possible to have them repositioned as they are in my first screenshot "GUITexturenButtons.jpg"?
     
  7. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Can you post the new code? Try printing out the values you get for the (x,y) position of the buttons. Just put the x/y parameter code into a print() method, and see where they are.

    Edit: On second thought those are size parameters, just set them as a value for now. Like 5 or so. Feel really stupid now for not actually looking over the code.
     
    Last edited: Apr 13, 2014
  8. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    158
    landon91235 I'm not quite following you, on the print() method. As for the code, I don't have anything new coded. It is all in this post, including what Blaveloper suggested. Is it posible to code me a GUITexture as baground and above that a GUIBotton, that can be rendered wihout losing their initial positioning in 480x320px and in 800x480px? That is what I want to achieve for my GUI in app, and learn from it.
     
  9. Blaveloper

    Blaveloper

    Joined:
    Nov 22, 2012
    Posts:
    46
    Maybe it would sound harsh, but do you actually have any idea what the error means?

    I used "browserWidth" and "browserHeight" as defined variables.
    Looking at your code, you didn't define them to begin with.

    Code (csharp):
    1. private float browserWidth = *ANY NUMBER*;
    2. private float browserHeight = *ANY NUMBER*;
    Keep in mind you replace "*ANY NUMBER*" by an actual number, like 1, 2, 3, 4, 4.5f, 4.6f, etc.
    Looking at your initial code, you have "browserWidth" set as 50 and "browserHeight" set as 35. Use these values instead of "*ANY NUMBER*".

    Sorry I didn't mention it before, I thought it might be obvious to you as well.



    As for the touch screen code, I don't use Unity for mobile devices.
    I use Unity for Wii U, the touch screen commands for Wii U work differently than for Android, iOS, Windows 8, BlackBerry and Windows Phone.
     
  10. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    158
    Hello Blaveloper. Well it seems it has been some time since you were a newbie at something. Anyway, I have them both declared at script, but on scene compilation I did not see any difference on changing screen resolution. Maybe combining GUIButtons on GUITexture is not a good practice to use in Unity resolution indiependent?
     
  11. Blaveloper

    Blaveloper

    Joined:
    Nov 22, 2012
    Posts:
    46
    Do you have a screenshot of the updated problem?
    No, using textures on GUI buttons shouldn't give any issues, although I didn't test my script against it.

    Yes, I'm still a newbie at mathematics. I don't know why.
     
  12. sootie8

    sootie8

    Joined:
    Mar 25, 2014
    Posts:
    233
    This scales everything to size with this pattern, probably would be more efficient to create and scale each rect in the start. This may stretch a little if you are using displays with different aspect ratios.
     
    Last edited: Apr 14, 2014
  13. Exnihilon

    Exnihilon

    Joined:
    Mar 2, 2014
    Posts:
    158
    Hello sootie8 and sorry for the late reply. Well I have tried the snippet code you posted, and it works fine on editor. My problem, that I also have a guiTexture as a background to the GUIButtons, that scales too, according to the screen size, but indiependently of the GUIButtons, therefore those two are always misplaced. See carefully my posted screenshot, and you may get to what I mean.

    I have come with an idea on how to make those two, guiTexture and GUIButtons, scale on every screen simultaneously. I thougth of using your script in an if ...else if... statement onGUI function, and hard code every GUIButton on the new screen dimention inside the if clause.

    Is this feasible, cause I cannot make it complile. Need help with this code:

    using UnityEngine;
    using System.Collections;

    public class GUIButtons : MonoBehaviour {

    public Texture btnTexture1;

    Vector2 ScreenSize;
    Vector2 ScreenSize1;

    void Start () {
    if(ScreenSize = new Vector2 ((float)Screen.width / 480f, (float)Screen.height / 320f))
    else if ((ScreenSize = new Vector2 ((float)Screen.width / 800f, (float)Screen.height / 480f))
    }

    //Draws GUI elements on 480 x 320
    void OnGUI(){

    if(ScreenSize = true)

    if (!btnTexture1) {

    Debug.LogError("Please assign a texture on the inspector");
    return;
    }
    GUI.Button(new Rect(68, 219, 50, 35), "");

    //Draws GUI elements on 800 x 480
    if(ScreenSize1 = true)

    if (!btnTexture1) {

    Debug.LogError("Please assign a texture on the inspector");
    return;
    }
    GUI.Button(new Rect(120, 250, 50, 35), "");
    }
    }