Thursday 20 January 2011

Lessons Learned

Well, we're pretty much wrapping up the first game now, fixing the last of the bugs and wading through Apple's release guidelines. I've experienced a lot of silly timewasting bugs/issues over the last few weeks which I could've easily avoided with a bit of prior knowledge; so with this in mind I've decided to talk about some stuff which might help out anyone who may be in a similar situation.

This discussion is specifically aimed at people developing for iOS with Unity.

The first item I want to bring up is textures, the only textures required in our game were GUI textures so with that in mind we created them exactly to size and imported them as GUI in Unity. The problem with this was that even though they were switched to 16 bit, they were taking up a massive amount of memory on the iPhone. This was made even worse by the fact that we designed the GUI for the 4th gen devices, so the full screen textures were 960x640, and we had a lot of full screen textures.
The solution to this problem was to simply reuse a couple of the full screen textures for backgrounds and then convert the overlying textures into powers of two so they could benefit from PVRTC compression. We were able to reduce our total texture size from around 50mb to 12mb, a much more acceptable number.

The second major issue we had was with meshes, luckily we managed to catch this quite early on in the development process so it turned out to not be such a major problem. The problem we had was that we had no idea what the constraints of the iPhone hardware was in terms of polygon processing, this information is actually available in the Unity help files but for some reason I hadn't been able to find it. To cut a long story short, Olly went a bit wild on the poly count and we ended up with around 70-80k polys on screen at any one time. This turned out to be about 70k more than was recommended so with some hasty remodelling we have a very safe poly count of around 3-4k on screen at any one time, this falls well within the recommended 10k. Once again this is a perfect example of where some prior research would have been really beneficial, as it is also clearly written in the Unity help!

Another issue we had to contend with was the resolution difference between the 4th gen devices and the older devices. The resolution of the new devices is 960x640 and as I mentioned earlier, we designed all our textures with this in mind. Fairly obviously this meant that I had to design the GUI elements to dynamically change based on the resolution, well I say fairly obviously, it clearly wasn't to me when I started. I decided initially to have two functions, one called DisplayHighResUI() and the other DisplayLowResUI(), I worked on this for a while before I realised that instead of declaring ExampleElement = 100; in the high res UI and ExampleElement = 50; in the low res UI; I could just work out the position based on the resolution. So in the previous example, ExampleElement = 100; could actually be ExampleElement = Screen.width * (100/960), or more simply just Screen.width * 0.1042.
This should have been obvious to me but it just shows how a lack of forethought can cause you to rush and then spend time repairing problems.

There were other issues we had involving game balance, particularly the time the game took to complete and the speed which the user had to react to events. These were quite specific problems though so I won't go into them here.

From my experience with developing our first game, I've compiled a top ten tips list for developing a game for iOS with unity:
  1. Plan - try and think of every problem you're going to encounter, you won't get them all but it will certainly help.
  2. Watch the size and use of your textures - try and get as many compressed to PVRTC as you can.
  3. Don't use too many polys in your models - 10k max on screen at any one time.
  4. Compress your sounds - I compressed our backing track from 1.4mb to 800kb with no noticeable loss of quality.
  5. Be object oriented - don't have enormous long classes, split them into smaller self contained classes.
  6. Be careful with OnGUI() - this function can get called multiple times per frame, so put as few calculations in here as possible. One bad example of this is updating a scrolling GUI element in here, it'll move faster and get called more often than necessary.
  7. Don't put everything in one class - I had a good example of this, I had a game class where the game logic was updated in Update() and the GUI was drawn in OnGUI(). This wasn't a good idea because the script file was huge, the update function also became extremely confusing as it was updating elements for both the game and the GUI. I solved this by creating a new class for the GUI and moved all the UI functions over to it leaving the game logic class much tidier.
  8. Pick a language at the start - I decided to go with javascript as most of the help examples I could find online were in java. Coming from a C++ background this was a bad choice and I wished halfway through that I'd gone with C#. My advice is go with what you know best.
  9. Watch javascript's dynamic casting - if you choose to use javascript, watch out for this one. iOS doesn't support it, so all your variables have to be statically typed: i.e. var x = 10; will work normally but on iOS you are required to put var x : int = 10; This nearly caught me out when passing variables in functions, the function definition must also include a type: function PassStuff( valueToPass ); won't work, you need: function PassStuff( valueToPass : type );
  10. Use the unity help - it's an invaluable tool and is extremely useful so don't neglect it.

No comments:

Post a Comment