How to Work With Different Screen Resolutions - android

I'm using Unity 4.3.3 for my game. I'm making a game for Android and iOS devices. Since I'm pretty new to unity, I can't seem to find a way to work with different screen resolution.
I'm using c# for my scripts.
I want my game to run full screen. I've tested it on iPad 2 and it runs perfect but for iPhone 4 the sides are clipped and for iPhone 5 they are clipped even more. What is the solution? Which option should I choose under Player Settings > iOS > OtherSettings > Target Resolution?

unity changes its ingame camera to match the dimensions of the aspect ratio of the screen it's using. Obviously this isn't always desired, so there's a couple of ways around this:
1) First method is very easy to implement, though it rarely looks good. You can simply change the camera's aspect ratio to match the one you've designed your game around. So if for example you've designed your game at 4:3, you'd do something like this:
Camera.aspect = 4f/3f;
Just keep in mind that this will distort the game on different aspect ratios.
2) The other method is a little more complex, but the result looks much better. If you're using an orthographic camera, one important thing to keep in mind is that regardless of what screen resolution is being used, the orthographic camera keeps the height at a set value and only changes the width. For example, with an orthographic camera at a size of 10, the height will be set to 2. With this in mind what you'd need to do is compensate for the widest possible camera within each level (for example, have a wider background) or dynamically change the Orthographic Size of the camera until its width matches what you've created.
GUI components are easier to implement simply by setting their position to depend on the screen resolution wherever needed. For example if you want a button to appear in the top right corner, you simply set its position to something like position = new Vector2(Screen.width - 50, 50);
EDIT: Since you mentioned devices you used, I did a bit of looking up to find what aspect ratio each one uses: Ipad2 = 4:3 , Iphone4 = 3:2, and Iphone5 = 16:9
Since you said it looks perfect on the Ipad2, I'm guessing you've designed your game to use a 4:3 aspect ratio, so the "clipping" you mention is just that your orthographic camera has widened. The solution is to use one of the two methods I described above.
You can see how it will look on each device within the unity editor fairly easily. If you go to the game tab (what pops up when you press play in the unity editor), you'll see it has a device name, along with a resolution and aspect ratio. Changing this will let you see what it will look like at different aspect ratios.

You may want to try capturing the device resolution by using Camera.ScreenWidth and Camera.ScreenHeight.
Then do some math to calculate the difference from the resolution you have and apply it to the parent object.
This will scale everything bigger/smaller to fit the device resolution without having multiple image resolutions etc for different resolution devices.

If your goal is to get the previous width:
[RequireComponent(typeof(Camera))]
public class ResizeCamera : MonoBehaviour
{
private float DesignOrthographicSize;
private float DesignAspect;
private float DesignWidth;
public float DesignAspectHeight;
public float DesignAspectWidth;
public void Awake()
{
this.DesignOrthographicSize = this.camera.orthographicSize;
this.DesignAspect = this.DesignAspectHeight / this.DesignAspectWidth;
this.DesignWidth = this.DesignOrthographicSize * this.DesignAspect;
this.Resize();
}
public void Resize()
{
float wantedSize = this.DesignWidth / this.camera.aspect;
this.camera.orthographicSize = Mathf.Max(wantedSize,
this.DesignOrthographicSize);
}
}

You need to change camera viewport according to device's aspect ratio.
Suppose you made the game for 720x1080
Then in the script you should do
float xFactor = Screen.width / 720f;
float yFactor = Screen.height / 1080f;
Camera.main.rect = new Rect(0,0,1,xFactor/yFactor);
Or
The another way is, if you are making a game for aspect ratio 9:16 then
Do this in your script,
public float targetRatio = 9f/16f; //The aspect ratio of your game
void Start()
{
Camera cam = GetComponent<Camera>();
cam.aspect = targetRatio;
}

I know it's an old thread, but people might still end up looking for an answer.
To adjust a perspective camera to different screen aspect ratios with different behaviour than the Unity default, you need some trigonometry. All the necessary info about that is here: https://en.wikipedia.org/wiki/Angle_of_view
If you want an easy way out, though, here's a solution that works with all camera types: http://u3d.as/oUX

Ok, this is a big question. Many people have referred to forcing an aspect ratio, which is a good solution to consider. However for many games this is not appropriate. For many game designs, you want the game to feel like it's native to the device/screen it's running on, and you want to use every square inch of screen real-estate you can. To do this, you must build and test every system in your game for different sized and shaped screens. It's a very similar problem to building apps and websites for multiple devices.
Screen Size
The screen size can be retrieved programmatically using the DPI and the resolution with a statement such as:
Resolution res = Screen.currentResolution;
float screenSquareInches = res.width * res.height / Screen.dpi;
For the content on the screen that is viewed through the camera, there's only one variable that needs to be scaled, and that's the size of the camera (or how much stuff in the game world that will be squeezed onto the screen). You can control the size of the camera with the field of view for 3D games or the orthographic size for 2D games. Only testing will say what equation supports the widest range of screen sizes, but something along these lines could serve well:
// this should be a tweakable number, so you can fine tune it to your needs. It represents the screen size at which the camera size should not be scaled at all
float expectedScreenArea = 20;
// this number should also be tweakable, which declares how much smaller/larger text can get depending on the screen size. Generally larger screens are viewed from farther away, so scaling should be slight
float cameraScalingRate = 0.25f;
// multiply this number by the default/base camera size you have picked, whether that's field of view or orthographic size
float cameraSizeMultiplier = 1 + (screenSquareInches / expectedScreenArea - 1) * cameraScalingRate;
Ok, that should get you most of the way on scaling the game world, but what about UI elements, things like text, HUD, and on-screen controls? Well, for elements like text, the above equation should work decently well, though you might want a different value for the scaling rate. For on screen controls, you might want a more full transformation, such as joysticks moving to the bottom corners of the screen on a tablet rather than centered on the sides, or if it's not a touch screen device, remove on-screen controls altogether. That's outside the scope of this question.
Screen Aspect Ratio
The aspect ratio of the screen (how wide vs. tall is it) is also important and needs it's own handling. Generally the best way to do this is to freeze the vertical height of the screen, so that as the screen gets wider, elements on the screen are not scaled, but as the screen gets taller, elements on the screen scale proportionally to how much taller the screen grows. This is already the default behavior for cameras, but for UI elements you have to set it as such. This is relatively easy if you are using the new UI system with canvas'. On a CanvasScalar component, there's a property that controls how the elements are scaled depending on the aspect ratio. Change this to match width or height, and have it match height.
For Further Consideration
With supporting different screen sizes and shapes there's more to consider than just making everything fit. You also need to make sure you game plays well on the different screens. This ranges from things as subtle as not making the player feel claustrophobic on a small screen to making sure enemies can't shoot at the player if they're off screen to making sure you update boundaries that keep elements on screen.
Another thing to consider if this is a PC game is that someone might plug their computer into a different screen or change the resolution on the fly. With this in mind, it can be good to rerun the above equations as needed so a player doesn't have to exit the game to get things lining up right again.

The easiest way I've solved this was as pointed out by Steven, force my perspective camera aspect ratio to the one I develop for. Of course this deforms some objects if the aspect ration I developed for is to different from the one of the device. For UI objects, if you are using the build-in, I create the rectangles based on a percent of whatever the screen size is
Rect(0.5 * Screen.width, 0.5 * Screen.height, 0.25 * Screen.width, 0.25 * Screen.height)
That will place the top left corner at the center of the screen and create a rectangle of 1/4 the height and 1/4 the width of the screen. I'm using NGUI 2.7 for the UI and I haven't seen any issues with different aspect ratios so far, and that one uses an orthographic camera to render the UI

If you are developing 2d game,that is your camera is in orthographic view then Just do the following code and attach it with your gameobject. It will scale the gameobject(in this case the sprite) with the screen resolution.
void Resize()
{
SpriteRenderer sr=GetComponent<SpriteRenderer>();
if(sr==null) return;
transform.localScale=new Vector3(1,1,1);
float width=sr.sprite.bounds.size.x;
float height=sr.sprite.bounds.size.y;
float worldScreenHeight=Camera.main.orthographicSize*2f;
float worldScreenWidth=worldScreenHeight/Screen.height*Screen.width;
Vector3 xWidth = transform.localScale;
xWidth.x=worldScreenWidth / width;
transform.localScale=xWidth;
Vector3 yHeight = transform.localScale;
yHeight.y=worldScreenHeight / height;
transform.localScale=yHeight;
}

There is a free asset in Asset-store regarding this issue...Just check out...
http://u3d.as/content/palash-bhowmick/fit-all-screen-size/9q9
if shape of your object is changed, then delete the lines which starts with:-
transform.localScale.x=

if You have no choice You also can Do some more work and add a special Script to your camera that:
checks Screen Resolution for device
sets the target resolution for that
and also sets the target aspect ratio for that (IMPORTANT)
all you need to do is just writing a base function for checking the screen resolution (both width and height for devices that you want) and then add some more functionality to that for setting the proper screen resolution and aspect ratio!

Its very easy for Unity Now as Unity3D has its own UI system. For 3D Unity Adjusts the camera Automatically with screen size.
Problem arises for UI actually and its a little bit tricky. First of all try to figure out which elements needs to change position and size with screen size.
For example if you have a button exactly in the center of screen. Then it doesnt need to change the position according to screen. It will remain in center.
Now lets take a scenario in which you have a button in the corner of screen like we see pause button in top right or top left. Now you will have to anchor your button in the corner accordingly. It doesnt matter on which screen size the game is running, the pause button should stick to the corner.
Now lets take another case in which you have a background in your menu. Now you will have to apply stretch for this BG sprite. This BG will be stretching and shrinking accordingly but all items on it will have a fix size.
For this it is recommended to have BGs flat so that a same BG can have a good quality for 16:10 or 4:3
(Its all about Unity Native UI)

Related

How do I ensure my UI buttons scale with screen size and orientation using unity?

This might be a dumb question but I'm using unity to build a double pendulum app and because not all screen sizes are the same the UI buttons get moved around and don't scale to match the phones screen size. I attached a few images to show you what I mean.
Notice how in the third image, the return button overlaps the other UI sliders. I think the issue is that the pixel distance from the top of the screen doesn't change given new orientation. Is there a way to keep the spacing proportional?
On your canvas object, set it to Scale With Screen Size then, set the Match property to 0.5. This way the canvas will scale with both width and screen height.
If you need more info about Designing UI for Multiple Resolutions, check here
Well in your parent cancas object in the inspector,the 2end setting there a a drop down. Click it than a magical setting scale with screen wil be ther.👍

Libgdx Positioning objects on same position in all resolutions

I'm newbie in libgdx trying to make a live wallpaper.
The issue is positioning of object in all screen size with different resolutions in android.
I'm using Orthographic Camera and FillViewport to support multiple screens using viewport https://github.com/libgdx/libgdx/wiki/Viewports.enter link description here
camera = new OrthographicCamera();
viewPort = new FillViewport(WORLD_WIDTH/1.1f,(WORLD_HEIGHT),camera);
viewPort.apply();
camera.position.set(camera.viewportWidth/2, camera.viewportHeight/2, 0);
where
WORLD_WIDTH=2048;
WORLD_HEIGHT = 1325;
I want to place an object on same position in different screens Like balloon on top of each screen. For this I tried to find percentage of height in given WORLD and on basis of that percentage I found hieght on screen but it appears different position ondifferent screens some time in middle of screen some time in bottom, some time on top and some type out of screen. :-( while I'm trying to place always on same height as it was in WORLD height. I used following code to compute that
balloonHeight = (((Gdx.graphics.getHeight()*1.0f)/WORLD_HEIGHT)) *
(WORLD_HEIGHT-(ballonSprite.getHeight()*((Gdx.graphics.getHeight()*1.0f)/WORLD_HEIGHT)));
ballonSprite.setY(balloonHeight);
I will be thankful to all of you kindly let me know issue and help me to understand what mistake I'm making.

How to decide WorldSize ,viewport for GamePlay and HUD

I am making a game ,having static gameplay(i.e fixed background).
I want to target devices having aspect ratio in range 1.33(800x600) to 1.77(854x480).
For my playArea i want a fixed aspect ratio.
For my HUD i want fixed position relative to Scrren Size
and i am using stages to implement HUD,gameplay area.
Note Here World Size refers to virtual size (as mentioned by Springrbua)
First Question- is that possible to target wide range of screens with constant worldsize or setting some ViewPort-(Stretch,Fill etc) ?
Second Question - what should be the world size in pixel so that i can create graphics acc to it?
Third Question - what should be viewport for HUD,Gameplay ?
My Experience...
I started a game with WorldSize (855 x 600) and Fill ViewPort for gamePlay and StretchViewPort for HUD.For gameplay so far is good , but i am facing many problems with HUD.Position of hud elements never reamain same whatever i do(fixed position irrespective of screenSize).
Last One - Is creating background of resolution 855x600 is right thing to do?
Plz suggests better alternative ,approach or what i am doing wrong.
Thanks in Advance.
sry for my bad english.
First of all: the world size is not the same as the viewport size (or virtual size in the text below):
Worldsize: Size of the level
Virtual size: Size of the levelpart/worldpart you can see on screen
Usually you can only see a part of the level and a Camera moves arround to show different parts.
If the whole level is shown on the screen at once, the worldsize and the virtual size are the same.
To keep everything as simple as possible, they should use the same units (for example meters).
With libgdx it is not only possible to have a fixed virtual size, but it is also pretty easy.
As you allready noticed, there are the Viewport classes, some of them support a virtual size to.
The Viewport you should use for your gameplay area is the FitViewport, which supports virtual size and keeps the aspect ration by showing black borders (for example a 16:9 aspect ration on a 16/10 screen will result in black borders on the top and on the bottom of the screen).
For the HUD you can use another Viewport, i guess StretchViewport is okay. It also supports virtual sizes, but instead of keeping the aspect ratio it stretches the things (for example the elements of a 16:9 virtual aspect ratio on a 16/10 screen will be stretched up and down) to fill the screen.
The virtual size you want to choose depends on the game. Just think about it this way:
What entities are there on screen? For example Humans.
How big are they in real life? Humans are about 1.75m tall.
How big do i want them to be on screen? A Human should be about 1/10 of the screen.
Okay, now you have 1.75m should be 1/10 screenheight. Therefore the Screensize is 1.75*10=17.5.
To have it a bit simpler, lets guess we have a bit taller (1.8m) humans and so our virtual height is now 18.
Now think about the Aspect ratio, i want a 16/9 aspekt ratio, which means, that 16/9 = width/*18*
Our virtual width is 32.
Now we have a virtual size of 32*18m. The bigest advantage: Everything can now be calculated in meters. If you want to move the human by 1m, just add 1 to its position.
As i allready said the Viewports can be FitViewport for the game, as you want to keep the aspect ratio and for the HUD i guess StretchViewport would be fine, but you can try out different ones and choose your preffered.
Hope it helps.

Android: Doing all my drawing on a SurfaceView; what's the proper way of making sure my drawing conforms to any screen size?

I'm making an app (a game, to be exact) where each activity uses a SurfaceView for the UI. All of the drawing is done through onDraw. I am also designing this to use no Bitmap assets, so everything that is drawn is produced directly by the app. I'm trying to design the app in such a way that it can easily be viewed on any screen size.
So here's how I'm accomplishing this: I'm doing my testing on a Galaxy S4, which has a screen size of 1080x1920. In the constructor for each activity, the width and height of the current screen are calculated and stored as ints "w" and "h" (the app is already locked in portrait). Then, whenever anything needs to be drawn onto the screen, I multiply the desired dimension (as seen on my 1080x1920 screen) by either w or h, and then divide by 1080 or 1920. Since I'm not using any Bitmap assets, I never need to worry about pixelated images or anything this way.
This gets the job done, but seems like a bit of a roundabout way of doing it. I figured there would be a better framework for getting this done, and I'm worried that these big calculations are eating into my drawing time (running at 30FPS can get a little jerky).
Is this is the customary way of doing it, or is there a better way out there?
There's a very simple yet effective way to do it, you can declare all your sizes in a dimen file for each specific density/size, as you usually do for layouts e.g:
values/dimens.xml <--- With default sizes
values-sw600dp/dimens.xml <-- Tablets sizes
(etc...)
Now before you start drawing, load all the values in your program only once, maybe onCreate of your drawing activity, using the following command:
float someItemSize = Context.getResources().getDimension(R.dimen.some_itemSize)
etc...
That way, you let the operating system do the pixels conversion for you, you should do it only once and most important, this will give alot of flexibility to your code because you will be able to change sizes from xml files without even touching your actual code, hence, the customization should be easier as well as future changes...
Hope it helps!
Regards!
There are two considerations: screen size and screen aspect ratio. If you simply scale everything to match the display, you will appear stretched a bit if you put a 4:3 device next to a 16:9 device.
You generally have two options for dealing with the aspect ratio: you can letterbox / pillarbox the output (which is fine for movies, but looks kinda lame for an app), or you can recognize that your output isn't always proportionately the same, and adjust the layout to fit nicely on the screen.
As far as size matching goes, when using a SurfaceView you can actually use a single size and then let the hardware scaler handle the rest. For an example of this, see the "Hardware scaler exerciser" in Grafika. I put a demo video here, though it's a bit hard to evaluate after getting rinsed through screenrecord + youtube. What you're seeing is the same couple of shapes rendered onto a Surface whose size has been set to an arbitrary value, and then scaled up to match the display. This is most obvious on the final setting, where it's drawing on a 106x64 surface.
With this, you could size your assets for 720p and always draw them the same way, and let the scaler deal with the stretching. See also this blog post.

On Gideros my game looks different on emulator and actual device

On Gideros I set the Logical Dimensions to 720x1080, with Scale Mode = Letterbox, and when I test it on the emulator with the same resolution it looks good, with no bars at the top and bottom or at the sides.
Then when I test it on a Sony Xperia T (720x1080 also) it shows a top and bottom black bar, with the navigation bar at the right side. It seems as if the navigation bar was interfering with the game's width, and so it loses width so the game will fit, ending up with the mentioned top and bottom black bars. Am I right? is that why I get those bars?
The problem also happens when I set the game's Logical Dimensions to 480x800 and change the images for that resolution. On the emulator works fine but on a 480x800 device it shows the same bars.
So my question is: Why am I geting the top and bottom black bars on my devices? Is it because of the navigation bar? How could I fix this?
PD: The game is on Landscape mode
Yes you are right
since onscreen "hardware" buttons does not count as part of the screen, the width then is smaller, thus you get the spaces.
(BTW you can change portrait to landscape in AndroidManifest to display buttons correctly)
More information on spaces and scaling
So you have a logical dimensions, for example: 480w by 320h (although they should be vice versa 320x480, (in logical dimension smaller always comes first) but thats another topic)
It means all your content must be prepared to deal with this dimensions.
But hey, not all devices have this dimensions right, so how to make it look similar on 800x480? You scale it up.
If the aspect ratio is the same (which is not the case in this situation as (480/320 = 1.5) and (800/480 = 1.66)) then you could simply scale up the scene with the one value for both width and height
But what if the aspect ratio is different
There are 3 ways to deal with it:
1) Stretching
We could stretch your width or height (what ever's ratio is larger) to fit the whole screen.
2) Cropping
scale by center to fill whole screen and crop out other what goes outside the screen
may not fit everyone but someone may use it.
3) Letterbox
It upscales to the maximal dimension of width or height, which fills the screen first, leaving whitespaces on other dimension.
What you choose depends on what you need to achieve, but my preference is Letterbox
And my suggestion would be, to prepare bigger BG graphics that go outside the screen (positioning them in the center of the screen using anchorpoint) and concentrate all the game on your logical dimensions.
Here's an example:
http://giderosmobile.com/forum/discussion/comment/13692#Comment_13692
Work with desktop simulator set with your logical dimensions if what is better for your, and change resolutions of the Desktop player to see how spaces appear and what BG pics may cover it
Another confusion may be, that by scaling in center, 0,0 coordinate is not in the left top position anymore (thus having spaces)
So what if I want to position object in the corner completely
Then as you did, ignore scaling by calculating the real offsets
http://appcodingeasy.com/Gideros-Mobile/Ignore-Automatic-Screen-Scaling-when-positioning-objects
Hope that helps :)

Categories

Resources