Creating a game for multiple devices (resolution and aspect ratio problem)

Started by
7 comments, last by hyperfine 9 years, 7 months ago

Hello

i am going to create a new 2D game by using Unity and C#

however i want my game to be for pc/ios/andriod devices, but as you know every device has its own resolution and aspect ratio.

so what is the better way to do a game for all of the devices without corrupting the images

someone told me to work in the highest resolution and aspect ratio available and just shrink your images later.

but i dont know if thats work and i dont know what is the highest resolution and aspect ratio for ios/android.

Thank you very much.

Advertisement

Scaling artifacts are horrible.

I have tried many different ways of handling variable resolution and I'm sorry to say there is no magic bullet

You have to make a value judgement on every part of the game.

3D is not a problem, you just have to be careful about mipmap distances, other than that it's fine.

2D is an issue.

For some parts of the game I typically store several versions of each graphic and load the one that is closest to the dispay resolution, other parts I use scaling, some parts I use construction.

Construction is where you store a single graphic, but pull it apart in rendering. For example a GUI frame. Instead of just blitting the image onto the screen I would render the fill, then the edges, then the corners. This way you haven't scaled any graphics in the blit, the corner is say 16 by 16 in the bitmap and 16 by 16 on screen. However you have to do multiple blit's when you would normally do one.

Sorry, no easy solution.

In 2D mode, Unity auto-scales so that the height is preserved (you don't have a say about it), and it clips by width to fit the aspect ratio.

I'd second your friend - start with a high resolution and a specific aspect ratio. Later on, you can hide certain elements, or move other elements you need to be at the edge. I've found that programming in Unity for different aspect ratios is not such a pain in the ass. I expected a lot worse :)

To make this work, create a big background - bigger than any resolution you'd normally support. Put at (0,0,0) - so that it is always centered. Make objects children of each other. Create a script that will position its GameObject at the proper edge (top|bottom, left|right) with random offset (x,y) when the scene is initialized (Start). You can use the main camera's aspect ratio (Camera.main.aspect) to determine the proper coordinates. Have in mind that origin in Unity is by default (0.5, 0.5) and that it uses Cartesian coordinates instead of the typical (0,0) for top-left corner of screen. Also, the default mapping is 100pixels=1 unit. Don't forget to set-up your orthographic camera for your default resolution (it's size is your default resolution's height / 200).

We use this and additional tricks to move objects proportionally (up to a point) for a second project, and it works quite well so far. The cool thing is that you can test it in the editor itself. The only problem with this approach (dynamic location by x based on aspect ratio) is that you need to run the game to see objects in their real position.

In 2D mode, Unity auto-scales so that the height is preserved (you don't have a say about it), and it clips by width to fit the aspect ratio.

the game i am going to make is 2D, i made a 2D game before and unity didnt auto-scale any images/sprites for me.

is there an option for it ? or is it a feature for unity pro?

Scaling probably isn't quite the correct term. First, you must develop for a specific resolution. Say, 1,280 × 720. Then you must set-up your orthographic camera's size in the editor. Since your development resolution is 720p, then the size is h/200 = 3.6.

If you develop for that resolution - that is - create textures and position them, not caring about resolution, the effect will be as follows:

  • Regardless of actual deployed screen size/resolution/aspect ratio, Unity will make sure that the y of your objects will remain as it looks in the editor
  • If the device's aspect ratio > the one you programmed against (>width), you will have extra space to the left and to the right
  • If the device's aspect ratio < the one you programmed against (<width), some things will be clipped to the left and to the right

This is why your background (and any parallax effects) must be a lot bigger than your target resolution (to cover bigger aspect ratio), and this is why you need a script to move objects (to the left or to the right). You can calculate how much based on Camera.ratio and Camera.size.

another option is to use a virtual coordinate system API, say 10000x10000. all 2d drawing calls use the API. the API converts to hardware coordinates as needed, based on the current resolution. it also calls the appropriate graphics library routine, based on the underlying graphics engine used. sprites are as large as possible, and scaled down using high quality sampling. lower resolution versions may also be used, with the API automatically selecting the best available for scaling. but you still need to deal with widescreen vs non widescreen resolutions with letterboxing to get the intended original aspect ratio at all resolutions. scaling down - not up, high quality scaling algo's, and multiple resolutions for source images (almost like mipmaps) help keep artifacts to a minimum. best of all, you can write all your 2d code to the API, then plug in any graphics engine at any resolution underneath it.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

For simple things like sprites, just create a series of them at different resolutions, choose the one larger than you need, use a high quality down-sampling filter to reduce to the correct size, then add a small amount of sharpening.

For textures that need to tile, do the same as above, except add a few pixels from adjacent tiles before you down-sample and sharpen. Then "cut out " the correct size you need: For example, say you have a series of tiles created at 64x64, 32x32 and 16x16, but you need one at 48x48 (64 / 1.333. = 48). Use the 64x64, add 4 pixels either side from adjacent tiles (or top/bottom) to make it 72 pixels wide, reduce by 1.333333 to 54x48 pixels , then chop of the extra the extra 3 pixels from each side. If you don't do this, the down-sampling or sharpening filters may leave visible borders at the edges.

For my 2D games on android, I support various screen size . I also supported various screen ratio once, but I decided to not support that from now, as it can be tedious to accomodate different screen layout.

Anyway, to support various screen size :

  • I generate one set of assets per screen definition (qHD, HD, FHD, QDHD). Note that i write screen definition instead of size because i will use the same screen definition for not so different screen sizes. e.g : 1024x600 will use qHD (960x540), as well as a qHD screen troncated because of the Android onscreen button bar (a case I had to deals with, very bad surprise).
  • In the program, I use the size of my elements for the used screen definition, and the reference size of the screen definition (e.g : qHD-->960x540), so that it's always adjusted to the screen.

Space Zig-Zag, a casual game of skill for Android by Sporniket-Studio.com

I don't intend to hijack this thread, but I have a similar question. Any responses are much appreciated, and hopefully it helps answer some of the questions OP has.

So I'm making a 2-D platformer that I want to have highly reminiscent of platformers from the 16-bit era, especially graphically. What I've done is created a number of rooms and sprites, which are composed of 16x16 pixel tiles. The issue is that people now-a-days are playing games on 1080p monitors, not the old-school small resolutions TV's of the 90's. What would be the best way to get the 16-bit feel on one of these monitors? I'm only using SDL as my API; I haven't explitly written anything for OpenGL yet. When I'm rendering, say, my character which is 2 tiles high and 1 tile wide (32x16 pixels), the SDL render function renders the character to be a given fraction of the total screen size that I've set. For example, if I want my character to be 1/16th of the screen width and the screen is 512 pixels wide, the character will be 32 pixels wide. This means that SDL has to upscale the sprite, which I've drawn to be 16 pixels wide, up to 32 pixels wide. SDL seems to do this, although there are distorting effects at certain screen sizes. For example, if I increase the screen to a certain size it no longer looks like the character is standing flush on the ground; there will be a small sliver of white background between my character and the floor. Any idea on how I should handle this?

This topic is closed to new replies.

Advertisement