Monday, September 2, 2013
Not much to report lately, I've been down in the weeds working on making all the UI elements scale and stretch properly for all possible aspect ratios, and it's been an utter pain, as I expected it would be. Nothing against Unity here, this is just one of those less-than-fun tasks that didn't seem necessary a while ago. Now that I plan to "support" mobile platforms, at least in a really basic way, this is just part of that process.
The work is not brain-busting so much as tedious. I pondered various methods and here's what I came up with: pick one square UI element (the player head on the left side). Calculate what the length of one side of it would be in relation to the height of the screen in your standard aspect ratio, the one you already like the look of. In my case this would be a 64 pixel square on a 600 pixel high screen, giving me a basic value for "headLength" of screenHeight * 0.106. I then use that headLength variable to lay out all the rest of the elements. The health bars are maybe a quarter of a headLength wide, separated by a gap of 1/16 headLength, etc. For the bus passes I start at the value of screenWidth and walk backwards across the screen to the left by various fractions of a headLength to get things placed and spaced properly. This way, when the game is switched to a 5:4 or 16:10 aspect ratio, the game gets the current screen width, calculates how long our new solomonic foot of headLength will be, then draws everything in proportion onscreen. You end up with versions of the UI that look a little different each time, but are close enough that the basic layout works across platforms. I have no idea whether this is a standard kind of method or a wacky backwards solution, and most of the Unity UI guides I have read are somewhat beyond my grasp so I just went with something that worked for this project, as I tend to do.
It is, if nothing else, a step up from the previous solution that I though was so elegant: arrange the UI objects in the scene view, far away from everything else, then create a UI-only camera that views them and layers that view on top of the game. This is still a cool strategy (I saw a talk by the Snuggletruck guys where they described something like this) but I'll be damned if I can get it to scale the way I need it to. In my version, the UI elements don't exist at all in scene view, they are only a collection of textures in a folder that are assembled and brought to life every tick with an OnGUI call.
That "every tick" is a big warning flag of course, and I've heard various rumblings about OnGUI being "expensive", in the sense that it's going to murder my framerate. It's true already that my mobile version is significantly slower than my webplayer version, but at this point I am at least savvy enough to beware that specter on the battlements pointing a bony finger at me and whispering "optimize prematurely!" That guy can go soak his head, he's not my real dad.