Monday, 1 September 2014

I've made a game - what did I learn?

I've made a game for iPhone, it's called Rebounder. This is a series of blog posts about it.
  1. I've made a game
  2. Why?
  3. How?
  4. Some of the challenges
  5. What did I learn?

It works in my head

Before starting Rebounder I came up with a few other game ideas and made a few prototypes. Each one was great when I imagined it in my head but sucked when I made a prototype. It really underlined the importance of getting software into people's hands as soon as possible.

There's no such thing as simple

Okay so Flappy Bird was pretty damn simple, but generally speaking there's no such thing as a simple game. When the idea popped into my head for Rebounder it was something like "draw lines on screen to bounce balls to a target, simple!". Unfortunately when you give it more thought and started building something, it's rarely simple.

Programmers can't make games by themselves

I have zero graphic design skills yet I still tried to create some graphics. It was a total waste of time, you need someone with graphic design skills. In fact I'm going to go as far to say that making a game by yourself is a bad idea. I think sharing work, sharing ideas, sharing enthusiasm, sharing testing and everything else would help a great deal.

Don't throw away your prototype

My prototype was terrible. Once it had served it's purpose, to prove that Rebounder would work, I had to start from scratch because the code was so bad. In doing so I reintroduced bugs I'd fixed and introduced new bugs, plus it took ages. In hindsight I feel that had I spent maybe 30-40% more time on the prototype I could have reused much more code and saved quite a lot of time.

Time management

Games take time and time is often in short supply. I realised during the course of development that I need to make better use of my time.
  • Prioritise - Only do what really needs to be done. Aggressively slim down your task list. For example split tasks into essential and nice to have
  • Discipline - When there's a lot of work to do I find it's important to find regular time, however short, to complete a few tasks so you feel like you're making progress
  • Focus - I spent a lot of time working in front of the TV, only half concentrating on the task at hand. Big mistake. It resulted in poor code and poor solutions. I really should have worked somewhere quiet with no distractions

Unity specific stuff

  • Don't use Vector2D to position your sprites - As far as I'm aware Unity has no mechanism for controlling sprite order so you have to set their Z co-ordinate so one is in front of another in the scene. This means you need Vector3D
  • Be careful when updating plugins - Make sure everything is committed to whatever source control system you're using before updating. In particular NGUI cause me some difficulties
  • Use Force Text asset serialization - The alternative, Force Binary, leaves you clueless as you what you've changed when committing to source control
  • Don't fight MonoBehaviour - By default all script components attached to GameObjects inherit from MonoBehaviour. When I started development I wanted to write POCOs so my classes were easier to unit test but I found many tasks were hard work because of the missing inherited functionality. In the end I gave in and wrote all my components that way. It was much easier
  • Keep your script components as small as possible - I found it's better to attach several small scripts to a GameObject rather than one massive script. In hindsight this is fairly obvious, it's just the single responsibility principle. The only downside to this a bit of extra code so the components can communicate
  • Events are invaluable - When I started writing Rebounder I had a lot of initialisation code that looked like this someObject = (SomeObject)FindObjectOfType(typeof(SomeObject)); This is really bad news because many of my classes ended up with unnecessary references to one another. Then, since I had a reference I would start calling the referenced classes methods and I moved closer to spagettiville. Using events these problems disappear. You simply fire off an event and any classes that need to know about it implement event handlers. The class firing the event and the class handling the event have no knowledge of one another. For event handling I used the Messenger Extended code on Unity3D wiki. I highly recommend it if you want a simple, easy to understand code that is up and running within minutes
  • Playmaker isn't particularly useful if you're a programmer - Playmaker is a popular plugin described as "visual scripting for Unity". What that means is you can make games without any programming knowledge. I attempting to learn it hoping it would speed up development time but ended up being frustrated because I could achieve things much quicker using code. Perhaps if I'd persisted with it Playmaker it would have been very useful, but then I would have probably had less Unity API knowledge. It's not black and white. Anyway, I gave up on Playmaker

Get lots of people to test

When I was ready to send Rebounder out for wider testing I asked on facebook and received what I thought was plenty of replies. I distributed copies of the game to less people than offered because I had enough testers. In hindsight this was a bad idea. Some testers didn't install the game and quite a few testers didn't offer any feedback at all. Perhaps they were busy or perhaps they didn't like it and were embarrassed to say. Don't get me wrong I appreciate everyone who gave up their time to test, but testing without feedback is totally pointless. So my point is, if you make a game or app, send it out to every single person who offers to test it.

Friday, 29 August 2014

I've made a game - some of the challenges

I've made a game for iPhone, it's called Rebounder. This is a series of blog posts about it.
  1. I've made a game
  2. Why?
  3. How?
  4. Some of the challenges
  5. What did I learn?

Learning Unity3D

Unity provides a very high level environment for making games, however that doesn't make it simple. Unity is a huge package with a steep learning curve for someone with no experience of making games. In addition to this it's not just Unity I was learning. Each plugin must be learned and I used several including 2D ToolkitNGUIGame Analytics and iTween. All but iTween required a significant time investment to get up to speed with.

Fortunately there are many great resources for learning Unity.

Different aspect ratios

There are a bunch of different aspect ratios being used by various phones on the market. Usually this isn't a problem. For example a 16:9 iPhone 5 will simply show a bit more on the left and right when compared with a smaller 3:2 iPhone 4 screen. Unfortunately the core gameplay mechanic of Rebounder is angles so that extra bit of screen means that sometimes a solution that will work in one aspect ratio won't work using another. The problem gets worse as the number of aspect ratios increases. This is one of the reasons I decided to stick with iPhones and avoid Android devices.



In my head this problem could be solved by using some clever maths to calculate the angles required and adjust elements of the level accordingly. One small problem, I'm not that clever. Another solution I came up with involved attaching a script to each target that stored positions per aspect ratio. So the co-ordinates could be (-10, 10) for a 16:9 screen and (-8, 10) for a 3:2 phone. I binned this solution because most of the levels worked fine in various aspects so I was duplicating lots of co-ordinates. 

My final solution was the simplest. If a level worked in all aspect ratios it would be loaded as normal. If a level was different for each aspect ratio the level name would include the aspect ratio. E.g. Level2-16by9 and Level2-3by2. The aspect ratio would be calculated when the game started up and appended to the level name where appropriate. 

2D graphics

Unity3D is primarily a 3D graphics engine. No really, it's in the name. When I started development Unity did not have:

  • A Sprite GameObject
  • Collections of sprites
  • A sprite animation editor
  • Support for different resolution textures on different devices

Fortunately a great plugin exists called 2D Toolkit which has all of these features. Probably the most useful feature I found was the Sprite Collections.

You simply drag all your sprites into the editor and 2D Toolkit automatically squishes them together to form a large texture atlas containing all your sprites.

Even better, for each sprite in the collection you can specify things like anchor position, the which point it rotates around; and the collider type, such as sphere, box or you can draw your own. If that wasn't enough 2D Toolkit also supports different resolutions so you can display sprites of an appropriate size for the device. For example x1 on iPhone 3, x2 on iPhone 4 and iPad 1/2 and x4 on iPad Retina.

The only feature I wasn't impressed with was the GUI system. For that I used NGUI. It's not cheap but worth it if you need a complex GUI or can pick it up in a sale.

I've only scratched the surface of what 2D Toolkit can do in this blog. Without it I'd probably have given up way before Rebounder was finished. 

Massive self doubt

I've never made a game before, I've never been involved in any game development and making games is really, really difficult. Because of this I went through periods of time when I thought creating a game was incredibly exciting and periods of time when I thought what the hell am I doing, this is a complete waste of time. 

What kept me going was taking breaks when I got very frustrated/bored/despondent and taking encouragement from positive feedback I received from friends having played Rebounder.


Making a game takes time. I, like every other software developer who ever lived, massively underestimated the time it would take to complete all the tasks and massively overestimated what I thought I could achieve. At some point I stopped and thought, this is getting ridiculous, I'm never going to finish, I need to cut down my work. So I did.

I used Trello to organise my tasks.

I divided my remaining tasks into two lists, one contained nice to haves and the other required tasks without which I wouldn't have a game. I ended up sacrificing:
  • Sound
  • Music
  • More levels
  • Game Centre integration
  • Push notifications
  • Minor improvements suggested by testers
  • Android and iPad support
If I hadn't done this I'd still be working on Rebounder now, with no end in sight.

Next blog post - I've made a game - what did I learn?