So I have been interested in the design of games for quite a while and making an original computer game is something I’ve wanted to do for longer than I remember. I have now (sortof) finished my first original game using the Unity Engine and have released it on itch.io for free. Full disclosure: this is not the best game that has ever been made, nor was it ever meant to be. This is a project that started off as a little experiment that eventually evolved into a game. Now that its done, I want to share some of the lessons I learned through this process.
Everything takes longer than you think it will
And I mean everything. Having done a few tutorials with Unity, and having done quite a bit of programming in the past as part of my job, after I had a working prototype, I thought that there wouldn’t be that much more to do. I then estimated the time it would take for each task that was left and that totalled around 24 hours or so to complete. In reality, I think that from that point the game probably took closer to 40 hours to complete.
One of the big things that took longer than I thought was the AI, but I’ll get to that later. Just getting things like the UI layout to look right and making sure everything works as you think it should takes a long time. What really takes a long time though is adding more features.
For example, I wanted to add to the actions that the player (and AI players) can perform. So essentially there are two main actions in the game: buying and selling districts. But the player can also spend influence to perform a lobbying action (i.e. lobby the city council to change laws etc) in order to change the underlying rules of the game, e.g. making powerplants give bonuses to residential districts instead of industrial districts. I made 10 of these special actions, and each one needed to be usable by both the player and AI players which meant that the AI needs to be able to judge when it is appropriate to use these actions. Also the turn controller, that deals with most of the maths in the game needs to know about any persistent effects, and one of these special actions must be able to turn off the effects of other actions. So this has already turned into a decent amount of work and then I decided to restrict the number of these lobbying actions that are available per game to 5 and randomise them. The randomisation itself is easy, but it added more work in that I now needed to have a script that would automate the generation of the Lobby menu, again not a huge amount on its own but I think you can see by now how a simple idea can quickly turn into more work that you initially anticipated. That said, I don’t regret taking the time for this process at all. It was a lot of fun and I learnt a great deal.
Art is hard
And I am no artist. I started off trying to draw some 2D sprites to use in the game. Honestly, from a technical perspective this would have definitely been the right choice: a few low-resolution 2D sprites will defintitely use memory than full 3D models. But I ran into a serious problem: it turns out I can’t draw. Now, I’m sure with a few years of practice I could probably make something acceptable for each of the five building types in the game… but I didn’t feel like I wanted to commit that much time and effort to learning to draw right now. I have other things I need to be doing.
On the other hand, I did know what I wanted for each building type. So first I looked around the internet at all the free assets I could find but, perhaps unsurprisingly, nothing really matched what I was going for. So I did something that I had no idea I would end up doing when I started this project. I downloaded Blender and started making some 3D models.
I was pretty intimidated when I first opened up Blender. Even more so when opening a third party asset in Blender caused it to crash immediately with no explanation or even acknowledgement that anything had gone wrong. However, once I found the Blender tutorials page and watched a couple of youtube videos, I actually found that putting together a few very simple 3D models was not only easier than I thought, but a lot faster than trying to draw 2D sprites to get the same effect. Now, the models in the game are far from professional quality, but they do the job and only took a few hours to get five distinct building types that cannot be easily confused.
If you are at all familiar with Unity, you will have noticed that the UI uses the basic Unity UI assets and not a lot else. To start with I was thinking I would give this an overhaul and create custom buttons etc but once the 3D models were done, I thought that the slightly shabby grey UI didn’t look completely out of place. I therefore decided instead to lean into this style a bit and found myself a retro-looking 8-bit font and used grey as the primary colour for the background on the information panels. Its certainly not to everyone’s tast but, all in all, I quite like the effect and it definitely saved me some time.
Sound really does make a game
Before there was sound in the game it felt incredibly flat, barely an interactive experience at all to be honest. As soon as I added some music and a couple (litterally two) basic sound effects is the moment when it actually began feeling like a game. I choose to use some simple 8-bit music and sound effects to lean into the simplistic artstyle and because they were some assets I had lying around from a humble bundle I bought a while back.
Much like the visual art, I think the music is unlikely to be to everyones taste but I really don’t care. I think its pretty catchy.
Even simple AI opponents are a bit tricky
So when I was working my way through some Unity tutorials it never occured to me that none of those games actually had anything like a proper opponent to play against. I think I now know why. AI opponents are a bit tricky, even very simple ones. Before I start getting into the details, it is worth pointing out that before I started this project I had never done anything quite like this and I didn’t bother reading anything or getting any advice on how to go about it. This may or may not have been a bad idea. Since releasing this game I have loaded a Unity AI book onto my Kindle. So far I have gotten as far as the Contents page.
Unless the computer controlled opponent actually makes use of machine learning methods, calling it an “AI” is somewhat generous, but everyone does it so whatever. As I said, I made this up as I went along but it works pretty well – I can only beat the hard AI through shear luck or cheating. Essentially my computer controlled opponents are a decision tree. In-fact the rough outline of that very decision tree is shown below (although a number of changes have been made).
Each step in this tree is trivial and boils down to a simple if…else… statement. However, when this all comes together it can become quite unwieldy. Importantly, nested if… else… statements are incredibly hard to read, incredibly easy to get wrong, and just terrible coding practice. So I broke the whole tree up into a series of states that the AI can be in, which are then checked in decending priority order. These states are: winning move (the AI thinks it can win this turn), prevent opponent victory (the AI thinks an opponent will win this turn), nearing end game (the AI thinks it can win in 5 turns or fewer), and normal game play (the default condition). The AI controller will then check each of these states in turn and when a state is true, the AI will then execute an if… else if… else… statement to decide which (if any) action to take. In hindsight this sounds pretty simple, but the hard AI controller is still by far the longest script in the game and any debugging takes a while, with small mistakes making a huge impact. The change from a “<” to a “>” meant the difference between an opponent incapable of making a move and one that I couldn’t beat.
Of course, once you have a computer opponent you will probablty also want to be able to set the difficulty level. To do this I came up with what I think is a pretty elegant solution. The hard AI is as described above, always taking up to five moves following the full decision tree. The pathetic AI, on the other hand simply buys and sells districts almost completely at random. This was a placeholder system that I used to test the game early in development but it was so convincing as a terrible player that I decided to keep it in. The “Easy” and “Medium” difficulty levels are set by the AI controller randomly deciding whether to carry out an action set by the “Pathetic” AI or the “Hard” AI, where the medium setting is more likely to choose from the hard tree than the easy setting. This effectively means that I get four levels of difficulty for the price of two.
You can probably tell that I had a lot of fun playing around with this AI system. For me, it is certainly one of the highlights of the project. I will get round to reading that book though and I’ve already been thinking about adding a seperate decision tree for mistakes that the “Easy” and “Medium” opponents can make if the random number generator is particularly unkind to them. I hope that might make them come across as more believable opponents.
New ideas are easy, deciding what ideas to cut is hard
I’ve already mentioned a few ideas I would like to have included but decided not to but that is really just scraping the surface. You might think that an idea is fully formed or even that you don’t have that many ideas for features, but once you actually start work on a project ideas come much faster than you could possibly implement them. I won’t bore you with a list of boring ideas that were never implemented. Instead, I’ll just bore you with an example of a feature that did stick around and one that didn’t make it into the game even though it would arguably add considerably more depth.
Deciding which ideas to keep and which to cut is really difficult. The game currently has four possible victory conditions (one of which can only be triggered in game). This would be an obvious thing to cut if I just wanted to save time or streamline the game. However, even though I know it wouldn’t come up very often, I really like the idea of being on the verge of defeat and saving yourself by changing the rules of the game itselfe. So the multiple victory conditions are here to stay. On a related note, I really like Fluxx.
An idea that didn’t make it into the game is bonuses based on adjacent tiles. Either owning adjacent tiles of the same type giving a bonus, or power plants only applying their bonus to adjacent tiles. Either way, I really like this idea. So why didn’t it make the cut? Unlike multiple victory conditions this idea came fairly late and is still a bit of a “oh I wish I had thought of that earlier” kind of thing. Because of that, none of the core infrastructure that runs the game is setup to deal with the problem. None of the cells know what their adjacent cells are doing, the turn controller does not know the identity of individual cells, and all of the maths is based on owned cell counts stored by each player object rather than carrying out a census of the board each turn. It would therefore take a major rewrite of some of the core systems of the game to implement adjacency bonuses and it just fundamentally wasn’t worth it at such a late stage in the project. I probably will implement something along these lines at a later date but for now I just don’t have the time. It would be nice to include at a later date to give the map layout some actual consequence.
So what next?
Next, why don’t you try out Hex Control over at itch.io (https://jakeward.itch.io/hex-control). Unfortunately it is only available for Windows but that might change in the future. The game is far from perfect but it was really important to me that I finish it and release it into the wild, so I’m very proud of getting it done. It is all too easy to just chuck things on the giant pile of unfinished projects in the corner of my mind when an exciting new idea comes along.
For me, I have a number of projects in mind. One of which is a platformer that I’ve already started working on this week with some (hopefully) interesting artificial gravity mechanics. More on that later though.
If you enjoyed reading this, why not comment below? Or check out my review of this Micronics case? It seems like a popular post for some reason… maybe I did good? No… that seems unlikely… Anyway…. Bye!