In a previous post I talked about a few stumbling blocks to supporting the three different iOS aspect ratios. To review:
iPad, iPhone4, and iPhone5 have different aspect ratios, and the iPad3 and newer have whopping big retina displays. This issue has some simple side-effects, like needing different splash-screen images. Not a big deal. More complex is how to handle this in-game. Do you have different sets of texures for each aspect ratio and maybe different textures for the iPad3 and 4? That’s tricky if you want to have a “Universal” app; one that can be loaded on any type of i-device, and still fit within that 50 Mbyte OTA download limit. One solution is not to care about the download limit. I didnt’ like that one. Or one could have two different versions of your app. That’s a potential QA problem and Apple (anecdotally) seems to like it better if you make Universal apps.
If you look around on the Unity3D iOS forum there are many many posts about how to handle this, and to be fair, many have to do with true 3D games and I was only concerned with Numberheads, my 2D puzzle game. So I don’t assert any sort of universal solution, sorry.
One way to lay out a 2D game is to have an Orthographic camera, a background image, and then to layer the other game elements (sprites, control buttons etc.) on top of that background layer. The background layer has no transparency, and the whole scene is often unlit so as to improve performance on mobile platforms. But how to reconcile these three different screen sizes:
- iPad3 (and newer) 2048 px X 1536 px
- iPhone4 (and similar sized iPod Touches) 960 px X 640 px
- iPhone5 1136 px X 640 px
It actually turns out that you can use the nature of the Ortho camera and automatic scaling(note 1) to solve the problem rather simply. Simply use a 1 pixel = 1 game unit sizing scheme for all of your game assets, size the background texture for the iPad3 screen size and then adjust the camera’s ortho size as appropriate. Here is an image that can help understand this:
This image (you can click on it to enlarge) is a screenshot taken right from Adobe Illustrator. Note that the HEIGHT of the image is 2750 pixels and the width is 1536 pixels. Huh? That doesn’t make a heck of a lot of sense at first look; doesn’t seem right. But, if you position the camera “above” the exact center of the image and pointing directly at it you can then adjust the camera for the different devices. The key is to keep your game elements inside the lines “iPad Top” and “iPad bottom”. The other devices (i.e., not iPads) will have some empty space, that is, the background (whatever you choose to show).
It’s easy to programmatically determine which device you’re on using the iPhoneGeneration enumeration. For iPad-type aspect ratios set the camera’s “Orthographic Size” parameter to 1024, for iPhone4-type aspect ratios set the size to 1160, and for iPhone5-type aspect ratios set the size to 1374. Note that you have to be sure to choose the correct size for iPod Touch devices as well, those are like one or the other iPhone, and note that (as of this writing) all the iPads have the same aspect ratio.
While this may sound a bit confusing, it works because the camera’s presentation is scaled to the physical screen size. Recall that the “Orthographic Size” parameter is “half of the vertical size of the viewing volume” (from the scripting reference). So if it’s set to 1024 for iPad then the vertical size is 2048 which maps 1:1 to the iPad3 screen pixel height in Portrait mode. But on an iPad2 or other 1024×768 devices, this 2048 x 1536 presentation is scaled to fit in that size.
Minor con – you need a huge background texture. But in actuality, if you compress the source image down to a square texture and display that texture on a cube with the Transform scaled to 1536 x 2745 x 1 you’ll have a “pixel perfect” display. That’ll look great even on the large Retina displays. Be sure to use the “best” RGB (not RGBA) Compressed PVRTC 4-bits compression and the texture will only be 2 mBytes. That’s a lot less space than if you needed three images, one for each aspect ratio.
This actually works in Landscape or Portrait orientations, has been tested on devices, and is in a shipping product on the App Store. Hopefully some Unity developers will find this information useful.
Note 1: The mechanism by which the scaling occurs is way beyond the scope of this post but can be seen by examining a built project’s “Classes/Unity” folder from within Xcode. Clearly I can’t post any of that without violating the Unity3D license agreement.