Monday, April 19, 2021

Post-Mortem: Containment Breach

 The first game I published was a little 2D top-down stealth puzzler I called Containment Breach. You can download and play it 100% for free from my itch.io page. CB was a huge step-up in complexity and quality from my first foray into Unity and as a result I learned a lot from the experience and expanded my boundaries quite a bit.

I expect the first two sections of this write-up to be more general design and conceptual stuff whereas the final two sections will deal more with the technical side of things. My goal is that this entire post is accessible to you regardless of your coding knowledge but if you're violently allergic to computer jargon you might want to check out after we get to the Nuts & Bolts section.
 
This article will spoil much of the game, so if you want to experience it the way I intended I recommend playing it before reading. The game takes new players about 30 minutes to complete.
 
 

The Concept

CB is technically my second finished Unity project; my first was a simple little shoot-em-up like Galaga that I made just to learn the absolute basics of Unity dev. So hot on the heels of that game, I knew several things:
  • I wanted to stay with 2D in a top-down pixel-art style.
  • I wanted to build off of the systems and mechanics I had already made.
  • I wanted to make a game with a world and discrete levels.
  • I wanted to increase the scope of my next project by a notch or two, but not go overboard.
A few ideas bounced around in my head, but the one that stuck was a Zelda-like, specifically the original Legend of Zelda on the NES. Though I haven't actually played the game myself, I knew enough about it to feel that it would be a good model. It had the perspective I was looking for; it had a static, handcrafted world with dungeons; each room was contained fully on-screen; it was grid-based, which I believed would reduce design and coding complexity; and it had top-down combat that would be fairly easy to adapt and evolve from my earlier game.

That being said, I knew immediately I didn't want to just clone Legend of Zelda. I wanted to make something that felt like my own. Not to mention that it's such a landmark game in a renowned series that there already exist clones beyond counting. So to put my own spin on things I made a couple of thematic decisions. Rather than the typical fantasy hero dungeon crawler, it would be a sci-fi game set on a Mars base and you would play as an alien escaping captivity. I've always enjoyed playing as aliens, monsters, and other non-standard creatures and characters in games so it felt like a natural fit.

The gameplay took a bit longer to puzzle out, and as I'll cover later on, the mechanics changed pretty dramatically over the course of development. But from the beginning I knew I wanted the player to have a melee attack whereas the enemies had ranged attacks (guns) to differentiate the two and emphasize the alienness of the player. I also didn't want it to just be hack-and-slash combat where you walked up to enemies and hit them until they died; I wanted the player to have to think and strategize about their approach, although I didn't know what form this would take yet. In Zelda there's a pretty big emphasis on exploration and discovery, so I thought that might be a fun element to incorporate as well; which did end up in the final game, though not in the way I originally intended.

 

The Design Process

I did jot down some notes for high-level features I wanted before I started work on CB, but for the most part I just dove into Unity and began building systems. Some mechanics were always intended to be there -- like the melee attack and the ability to eat other lifeforms to gain health and abilities. Others arose during development because their need became obvious once I had basic systems in place. To a certain degree, CB felt like it designed itself organically and I was just there to guide it.
 
The entire genre of stealth/puzzle game actually came about as a natural consequence of systems rather than my conscious decision. I knew I wanted my melee combat to require thought, but since the game's scope was small and the perspective was top-down I knew that some complicated fighting system was out of the picture. So my next thought was to use cover to close the distance to enemies with ranged weapons. The concept of a stealth game came soon after; it felt very appropriate for an escaping alien test subject to lurk around corners waiting to surprise a gun-toting marine.

That being said, there were times where I knew I needed to add depth to the gameplay but didn't know how. When it was time to brainstorm a new feature like this, I sat down and looked at what I already had. Were there any bugs to fix? Did anything feel too easy or too difficult? Too clunky? If so, how could I fix those problems in a way that moved me forward and was in line with the game's theme? I had lots of ideas that I left on the cutting room floor, sometimes after completely finishing and implementing them (which involves animating their art and writing their code). A lot of the ideas just weren't fun, or didn't mesh with the theme or mechanics I already had, and rather than find an excuse to crowbar them in I just filed them away as lessons learned and experience gained. I would much rather have a tightly-focused game than a bloated one that displays every idea I ever had.

One of the most challenging aspects of CB's development for me was the level design, since that's both a technical and a creative problem with no one correct answer. There were generally two approaches I took to designing levels:
  1. Design a scenario that teaches the player something new
  2. Put things together in a new, arbitrary combination and see if it's fun
One of my thematic inspirations for CB, as well as one of my biggest game design influences generally, was the Half-Life series by Valve. One of the things I admire most about the Half-Life games is how they teach the player about the games' mechanics. Namely, they teach you mechanics by showing you them rather than telling you about them. They introduce new enemies in a safe environment orchestrated to show off how they work and by making the way to deal with them the obvious, intuitive solution rather than drowning you in paragraphs of explanatory text. Mark Brown of Game Maker's Toolkit does a good job illustrating this point in this short video.

This made my job designing levels much more straight-forward; whenever I wanted to add a new type of enemy or hazard, I needed a level that explained how they worked. In CB, when explosive barrels are introduced there is one placed in your path in such a way that you cannot proceed until you try attacking it, at which point you learn they spark for a second before exploding, possibly killing the marine guarding it (or damaging the player if the player doesn't instinctively move away). Likewise, when electric floors are introduced the player must walk on them to proceed, so they know they can only do so safely for brief moments at a time. By introducing only one new thing at a time, I could easily increase the difficulty from level to level by weaving old mechanics in with the new one, since by getting this far the player has already proven they understand the old mechanics.

It was only when I ran out of new mechanics to tutorialize that I scratched my head designing levels. There were only a few of these per chapter in CB -- generally the later levels in each chapter -- but they were by far the most challenging. For these I basically just drew a shape for the room and then placed hazards into it in a way that seemed interesting and slightly more difficult than the previous level. Typically these levels would be totally scrapped and remade several times before I hit upon an iteration that I thought was both fun and didn't re-use a puzzle from a previous level. This part of the game dev process was probably the most frustrating for me as the developer because I just had to trust my gut when it was "good enough." There was no obvious sign that I had found the solution, because there wasn't one. 
 
I have always struggled with perfectionism and I'm deliberately practicing the skill of throwing up my hands and declaring that I'm going to stop fiddling with it now because otherwise I'll never stop. I sincerely believe that knowing when to stop (and being able to) is one of the most valuable skills in any creative endeavor.

 

The Nuts & Bolts

Here we enter the most technical section of my analysis, but I hope that even if you don't code or do game dev you'll be able to understand what's going on at the high level.

Since this was one of my first Unity projects, I was still learning how the engine works and what good practices are in it. I was already proficient with C#, the language with which you code in Unity, but I was a bit rusty coming into this project and in any case I had to learn a bunch of Unity-specific things as I went along. Therefore, my code and coding practices for CB were functional but very suboptimal. I'm not ashamed of this; if you don't do something badly you'll never learn how to do it well afterwards. 
 
However, the ever-growing spaghetti bowl of code I was writing quickly became the biggest limiter for my motivation and progress. Here's an example: in Unity, all GameObjects are built out of discrete scripts called Components. This forms a very modular and extensible system, but it does mean that if Components ever have to talk to each other you need to enable their communication somehow, such as by passing a reference to the first Component to the second one. Depending on how you do this, this can easily bloat your code and Unity's object inspector.

Like this. All the fields highlighted in red are references to other Components on the same GameObject. This example here doesn't take up too many lines but if you ever forget to hook up those Components into the correct fields you will experience a lot of annoying bugs.

This was compounded due to the make-it-up-as-you-go style I was developing the game in. That works alright for design, but not so well for coding. I never sat down to decide on a unified style or convention for the game's code, so a lot of systems that could be similar use wildly different structures. Put two-and-two together and whenever I wanted to modify something, I had to first re-learn my own code for that script, then check every other script that references the modified script and make sure I didn't just break those too. Quality of life features in Unity and Visual Studio make this a bit easier but not so easy that it didn't teach me a lesson in planning and consistency.

Some game mechanics changed as a direct result of my coding inexperience, too. I mentioned earlier that my plan was for CB to use grid-based movement the way Legend of Zelda does. The reason for this was because I thought it would make my job easier and keep the scope small, because it would reduce the granularity of movement and give me more control over where GameObjects could go. Once I actually implemented grid-based movement, though, I came to realize that restricting the player and enemies actually yielded more work for me and more complexity in my code. I don't know the NES's machine architecture but it may be that for games on that system grids made things simpler. Unity on the other hand has no grid unless you impose one on the game and imposing rules will always make your code more complex, regardless of what effect it has on the gameplay from the player's perspective. So the grid was scrapped and now in CB when you move you're moving according to Unity's distance units.

Likewise, if you've played CB you may have noticed that enemies never deviate from their patrol routes; the most they'll do is stand still and pivot in place. Originally I was hoping to have the marines seek you out if they spotted you, but once I imported an A* pathfinding algorithm and looked through its many functions I quickly realized I was about to massively over-scope my project. So I left it out for now in a bid to keep my sanity and motivational drive for my first big project. As a result CB became much more of a puzzle game than a combat/evasion game and is probably better for it.

 
 

What I would do differently 

The reason I didn't do a lot of things I originally wanted was due to my inexperience with Unity and/or my desire to keep a small scope. Other things I fixed due to tester feedback before the public launch on itch.io, such as the control scheme (originally, you attacked and shot spit into the direction you were facing rather than at the mouse cursor. I think something like 9 out of 12 people who played it complained about the old controls).

That being said:
  • I would write cleaner code using events via the Observer Pattern rather than a sprawling spaghetti bowl of scripts all directly referencing each other. This would have enabled me to add more levels and support the game with new content without pulling my hair out from constantly breaking everything every time I changed anything.

  • I would add a save system. I have no good excuse for why I didn't include it in the public release; I was just ready to be "done" with CB and it seemed like it didn't strictly need to be there. All it would really need would be to save which chapters and achievements you had completed, and would open the door to things like recording your personal best times and such.
  • Unlocking achievements is really underwhelming, especially considering how absurdly difficult the achievements are, so I would spice up the end screen with some animations and particle effects when you earned one.

  • Although overall I'm quite happy with the level design, there are some oddities. Chapter 3 includes a room with a locked door that is unlocked by destroying a missile turret instead of the usual computer. This is the only time in the game the computer is replaced with something else and I wish I would have thought to signal that this was possible beforehand.

  • I was still getting my sea legs with regards to pixel art and animation, so a lot of sprites in the game have a wonky perspective or aren't entirely clear as to what they are. I had a couple testers comment that they didn't realize pits weren't just walls, and although I tried to adjust the sprites to improve this I'm not convinced I made it clear enough. I also seriously cut corners with animation, particularly with regard to the player character and with corpses. I don't think this has a big impact on the game but it irks me and in the future I would like to improve in this area.

 Anyway, I ought to stop now or else I'll never publish this post. In the future I hope not to dump all this on you at once and instead write periodically as I develop. Thank you for reading, and I hope to see you again!

3 comments:

  1. Really enjoyed the game and the article. You did a great job explaining the code; I understood everything you said, and I have zero coding experience. -Shelby

    ReplyDelete
  2. Thanks for sharing your game and the experience of making it! I tried to get some of those difficult achievements, but could never pull any of them off.

    ReplyDelete

Post-Mortem: Protect & Serve

 A couple weeks ago I participated in my first ever game jam! This is something I've wanted to do for over a year now, but in the beginn...