When the screen resolution is changed at game start is the only way to get a guitexture to resize is to script it? Meaning there is no default settings for auto resizing.
There are no auto-resizing options for the GUI but it usually isn’t too difficult to implement in a script. A common technique is to design the GUI for a particular resolution and the use the GUI matrix to rescale it for the screen size. Say you originally designed the GUI for 800x600. You can use the following code at the start of the OnGUI function to scale to the screen size:-
var horizRatio = Screen.width / 800;
var vertRatio = Screen.height / 600;
GUI.matrix = Matrix4x4.TRS (Vector3(0, 0, 0), Quaternion.identity, Vector3 (horizRatio, vertRatio, 1));
Whether or not the images, etc, will distort in an aesthetically pleasing way is another matter
Thanks. I’m still trying to figure it out though. I’m trying to have a guitexture with its ability to change color and scale. That will adjust to screen res. Because the problem i’m having is i have a health and exp bar that is controled by code to scale its pix when damage. But that bar moves out of the screen when res is changed so i’m trying to have it adjust to the res. The thing is i’m not finding anything on how to get a guitexture in a guifunction group or layout area.
So how would i fix this problem or go an alernate direction?
You can’t render GUIText/GUITexture objects into the compound controls of the GUI/GUILayout class. It’s probably best to use GUI.Label to replace GUITexts and GUI.DrawTexture to replace GUITextures.
I like the Matrix idea but if you are interested, I wrote a script a while ago that I have been using all this time that might just help you out…
Basically, you hard code your desired screen resolution (in my case, I opted for 800x600), then , you define an area where you want something to be placed (one of 9 locations varying combinations of middle, top, bottom, left , right and center).
Now, what it does is, you give it screen coordinates as if the resolution is always 800x600 but if the screen is actually smaller then it will scale down the area to match. So if you defined the top right corner to use an image and the size you gave that area is 1/4 the size of the screen and you then scale the scene down, the area will always return the top right 1/4 the size of the screen.
on the other hand, if your resolution gets larger, instead of just stretching the area to fit, the areas you defined are then repositioned and takes up the exact pixel size you defined but oriented according to the borders you set for the area of the screen you were using.
An example use would be something like this:
var TopRight : ScreenArea;
var HealthBar : Texture;
function Start()
{
//this would be setup in the inspector...
TopRight.BorderH = 5;
TopRight.BorderV = 5;
TopRight.Size.width = 200; //quarter of the screen
TopRight.Size.height = 150; //quarter of the screen
TopRight.Position = eScreenPosition.TopRight;
}
function OnGUI()
{
var pos : Rect = TopArea.Area();
GUI.DrawTexture(pos, HealthBar);
}
So if you scale the scene down to iPhone size, the TopRight.Area() will return Rect(355, 5, 120, 80) but if you scale it up to 1024x768 it will return Rect(819, 5, 200, 150)
if this might be of use to you I wouldn’t mind uploading it when I get home… Just let me know if you would want it or not
I’d like to see the code if you can upload it.
enum eScreenPos {
TopLeft = 0,
TopCenter = 1,
TopRight = 2,
MiddleLeft = 3,
MiddleCenter = 4,
MiddleRight = 5,
BottomLeft = 6,
BottomCenter = 7,
BottomRight = 8
}
class ScreenPosition extends Object
{
var scorePosition : eScreenPos = eScreenPos.TopRight;
var width : int = 255;
var height : int = 124;
var borderHor : int = 0;
var borderVert : int = 0;
private var _area : Rect;
function GetArea() : Rect
{
return _area;
}
function DefinedArea() : Rect
{
var posLeft : int;
var posTop : int;
var tempRec : Rect = CalculateScreenArea(width, height);
var wPC = tempRec.width;
var hPC = tempRec.height;
switch(scorePosition)
{
case eScreenPos.TopLeft:
posLeft = borderHor;
posTop = borderVert;
break;
case eScreenPos.TopCenter:
posLeft = (Screen.width / 2) - (wPC / 2);
posTop = borderVert;
break;
case eScreenPos.TopRight:
posLeft = Screen.width - wPC - borderHor;
posTop = borderVert;
break;
case eScreenPos.MiddleLeft:
posLeft = borderHor;
posTop = (Screen.height / 2) - (hPC / 2);
break;
case eScreenPos.MiddleCenter:
posLeft = (Screen.width / 2) - (wPC / 2);
posTop = (Screen.height / 2) - (hPC / 2);
break;
case eScreenPos.MiddleRight:
posLeft = Screen.width - wPC - borderHor;
posTop = (Screen.height / 2) - (hPC / 2);
break;
case eScreenPos.BottomLeft:
posLeft = borderHor;
posTop = Screen.height - hPC - borderVert;
break;
case eScreenPos.BottomCenter:
posLeft = (Screen.width / 2) - (wPC / 2);
posTop = Screen.height - hPC - borderVert;
break;
case eScreenPos.BottomRight:
posLeft = Screen.width - wPC - borderHor;
posTop = Screen.height - hPC - borderVert;
break;
}
_area = Rect ( posLeft, posTop, wPC, hPC);
return _area;
}
function CalculateScreenArea(w : int, h : int) : Rect
{
var rec : Rect = new Rect(0,0,w, h);
if (Screen.height < 600)
{
rec.width = Mathf.FloorToInt( Screen.width * (1.0 / (800.0 / w ) ) );
rec.height = Mathf.FloorToInt( Screen.height * (1.0 / (600.0 / h) ) );
}
return rec;
}
}
Cool, thanks!
How would you go about changing the aspect ratio in your output? Would you change some of the hard-coded values in the script?
Just replace the 600 and 800 in the CalculateScreenArea() function to whatever you want to be your target screen resolution.
Everything else you do is then relative to that. This means that if you define a rectangular area in an aspect ratio like 16:9 but the person using your software then changes to an aspect ratio of 4:3 then your defined area will distort to be more in line with the new aspect ratio…
If you set the x scale of a GUITexture to, say, .5, then it will be 50% the screen width, no matter what the resolution is. If you set it to .2 then it’s 20% of the screen width. Same thing for the height. If you set the x position to .5, then it appears halfway across the screen, same for y position and height.
However, you still have to do scripting if you care about the aspect ratio appearing correctly. For example, if you have a circle made with a GUITexture like this and scale it so it’s perfectly circular on a 16:10 display, it will be distorted on 16:9 or 4:3 unless you compensate for that.
–Eric
I just call my function screenRect which excepts coordinates to be in screen coordinates (0,0 to 1,1) and then will return the actual rect.
public static Rect screenRect(float tx,
float ty,
float tw,
float th)
{
float x1 = tx * Screen.width;
float y1 = ty * Screen.height;
float sw = tw * Screen.width;
float sh = th * Screen.height;
return new Rect(x1,y1,sw,sh);
}
excuse me, where do i must to put this script… just into the camera, or in every GUI’s related gameobject?.. Thanks.
Once assigned, the GUI matrix stays the same until you assign it again. If the whole GUI needs to change resolution throughout, then you could just put this code in the Start function of one of your objects. If you need to go back to the default resolution at any time, you must set the matrix before rendering any GUI elements that will use it.
ok thanks !..
I set it in the start of one of my objects, but its returning a null reference error. I’m totally noob btw
What am I doing wrong?
Before that:
I’ve tried to manually multiply screen cords to a resize factors like:
ResizeX: Screen.width/600;
ResizeY: Screen.height/800;
and everytime i draw a gui i multiply the x and y cords by those factors, but the results of those divisions are always 0 or 1 instead of a damn float, so its not resizing anything.
i hate Gui.
You can solve the division problem by using a decimal point in the numbers:-
resizeX = Screen.width / 600.0;
Without it, the 600 is treated as an integer and since Screen.width is also an integer the compiler will use integer division. As for the null reference, perhaps you can post your code and state which line of code is throwing the error.
Andeee,
Does this also scale any fonts accordingly to on iOS/Android devices?
At the moment I have three sets of fonts which I switch between based on screen resolution but this would be a much better way to do things…
Regards,
mm
The GUI.matrix line only works in the OnGUI function, you get the null reference error if you put it in the Start function
And as far as I can tell the text does scale with the GUI but the results aren’t pretty if you go to the extremes
I doubt it will. The problem is that Unity iOS isn’t able to scale fonts at all - no matter what you code. You will always need at least 2 fonts (retina/normal DPI) for each font size you need.
Oh and I just want to say to everyone: avoid using the scale matrix Unity gave us. It scales the buttons and fonts pretty ugly and rapes the user interface pretty badly. Take some time to write your own wrapper class around the Unity GUI class, it took me some time to get a perfectly scaling interface without any quality losses or aspect ratio problems, but it’s worth the effort. You should always maintain the aspect ratio of your interface no matter what the aspect ratio of the screen is - just scale both height and width of your GUI elements relative to the height of the current screen resolution. After that, calculate the new positions of your elements based on both the screen resolution and the size of your GUI.
does this works only in builds.? in editor i cant get it work…