LD41 Postmortem Part 2: Building And Reflecting
As I said in Part 1, Ludum Dare 41 was my first game jam, and I was determined to produce a complete game. Part 1 describes how I picked an idea based on some criteria I laid out, and in this second and final part, I’ll describe what went right and wrong in making the game.
As a reminder, the theme of Ludum Dare 41 was: Combine two incompatible genres.
So, my concept was this: Combine FPS with a cooking game. Shoot monsters and throw their bodies into a stew in the middle of the level, based on a provided recipe. Simple enough, right?
Some important links:
What Went Right
Simple enough idea to execute
Now that I’ve gone “full-time indie,” I’ve obviously had to learn a lot more game programming… but I’m still learning just enough to do what needs to be done, so I can do it and move on.
All that is to say that when I decided to make a first-person shooter using Unity, I would be doing a fair number of things that I had never done before. Because of that, the concept needed to be simple enough that I could dedicate time for trial and error for the stuff that was new to me.
Fortunately, the number of components for a game like this is fairly small. To get an idea of exactly how small, check out the scripts folder here and you can see just how few scripts there are to make the game work: https://github.com/swivelmaster/ld41/tree/master/UnityProject/LD41-Nemoyten/Assets/Scripts
- FaceCamera (For rotating the quads that act as billboarded sprites)
- GameStateManager (Manages recipes and spawning enemies)
- Rotator (All this does is rotate the stew so it looks animated)
(Note that since I entered the Compo, I needed to make the source code publicly available. I also included my Photoshop and Logic project files as well.)
The art requirements were fairly light as well, and I decided that the enemy art was going to be childishly simple on purpose, and everything else was just going to be simple and would more or less look like what you might call Extra-Shitty Quake.
In order for a cooking game to be interesting, you need multiple ingredients… which in this case also means multiple enemies. And for multiple enemies to be interesting, you need different behavior.
To keep things simple, I wrote down some enemy types: Basic, Projectile, Fast Tank, Flying, and Big Bad. Knowing that those were my goal types, I could design an Enemy component with adjustable parameters for health and projectile firing. (I then doodled some weird enemy designs based on puns, and that’s how I do game design, everyone!)
I also used Unity’s built-in NavMesh components for enemy movement AI. Those components have some parameters that can be adjusted to change the enemy behavior, like movement speed, and turning radius.
Combining my Enemy component with the navigation component gave me just about everything I needed. I made sure to include an Awake Distance parameter – this determined how close the player needed to be for the enemy to become aware of them and begin pursuing and/or shooting them. I also adjusted the settings on the NavMesh Agent so that projectile enemies would stop short of the player so they could shoot, while the non-projectile enemies would get all up in the player’s business.
I ended up cutting the Flying enemy because I didn’t want to spend time writing any more navigation code, and if the flying enemies were just using the nav mesh but higher up, they wouldn’t really be very different from the other enemies anyway.
Adding Some Juice
I decided in the first few hours of development that I wanted the game to be as juicy as I could manage in the time I had. Players needed to know when they were hitting enemies, and when enemies were hitting them. Death had to be dramatic and entertaining. And very importantly, players needed to know when enemies became ‘Awake.’
I made sure to spend a few extra minutes on all of these details. There are little particle burst explosions for when the player hits an enemy. And there’s a burst of ‘blood’ coming from the player’s perspective whenever they’re hit.
I also took a swing at game sound design, which I had only really done once as a quick pre-alpha pass for my game-in-progress, Moustachevania. I used Logic’s built-in drum sounds plus a ton of reverb and effects to make explosion and shooting sounds, and I used my own voice (hey!) for almost everything else. I even did my version of the Quakeguy jump grunt, even though jumping really doesn’t add much to the game.
The sound of enemies going into the stew is a combination of an SP12 drum machine crash cymbal and me blowing bubbles into a large glass of water.
In general, I think I pulled it off; The game feels responsive and sounds pretty good.
I didn’t get this 100% correct, though; Many players didn’t notice the ‘Awake’ sounds – they were a combination of too quiet and not dramatic enough.
Playing To My Strengths
While I did set out to do something new from a tech standpoint, I also wanted to make something that was distinctly… me. The game combines a lot of disparate things I love: Retro first person shooters, weird monster designs, bad puns, serious parodies of seriousness, goofy sound effects, unsettlingly weird music, etc.
It was enormously satisfying to make. And some players, I think, even appreciated the jokes!
What Went Wrong
No FPS Dry Run
I didn’t know for sure what genre I was going to tackle before the theme was announced… but I’ve always wanted to make an FPS myself and I never got around to it. There were a lot of components I used for the game that would have been common components for any FPS, and if I had just spent a few hours at some other time to learn them, I would have saved a few hours of learning them during the compo time.
I followed an FPS controller tutorial to build that component quickly, and at some point I switched the movement method to one that (accidentally) ignored collisions. The result of this was that the player could walk through walls, and I didn’t really figure out that this was the problem until after the deadline. It actually doesn’t affect gameplay too much, but it was a frustrating rookie mistake!
Similarly, I learned NavMesh more or less from scratch during the jam. It’s not difficult at all (in fact, I was amazed at how easy it was, with one caveat I will describe below) but still… I should have done a dry-run with it earlier just to get familiar.
Before I set up NavMeshAgent, I had a Rigidbody on enemies and used it to add some recoil whenever they were hit by a player bullet. Once I added NavMeshAgent, things got weird.
I spent a whole lot of time trying to figure out why my movement seemed to get so buggy once the enemy was moving and then was hit by a player bullet. Turns out, the instructions for NavMeshAgent explicitly recommend not to move its Rigidbody while active, because they both end up fighting over moving the GameObject.
Ultimately, I had to ditch the recoil feature and just make the enemy pause their forward movement when hit.
Of course, there’s an easy way to do this involving turning the agent off. Or, you can actually just extract the directional information from the agent and apply force in the right direction to the Rigidbody manually.
In other words, there are ways to solve the problem, but because I was inexperienced, sleep-deprived, and in a hurry, I just wasted a bunch of time trying to salvage a feature that I had to abandon.
Physics Are Hard
To add onto to the previous problem, I also wanted to let players push the enemies around when they were dead in order to put them in the stew.
Turns out, this is hard. Or rather, it requires more knowledge of Unity’s 3D physics than I had and was willing to learn in the short time available.
Fortunately, I came up with an alternate solution: Picking them up and throwing them. This solution actually turned out to be more fun than pushing them around would have been, so ultimate it worked out. Still, it was another time sink.
Too Loose With The Theme
This is something I was worried about when I started building the game, and the Ludum Dare reviewers confirmed it: The genre combination wasn’t all that interesting from a gameplay perspective.
In concept it sounds pretty cool, but in execution it was functionally not all that different from a fetch quest in a first-person RPG, or any of the “pick something up and move it from here to there” puzzles in Source-engine games.
As such, ratings for Theme and Innovation were lower than I expected.
Wrapping It Up
I think one of the most interesting psychological aspects to creating art is that we always come up with different criticisms of our own work depending on what phase of creation we’re in. Putting it in front of an audience triggers deeper examination and, if it’s still possible, fine-tuning, for instance.
I decided to wait until LD41 ended and scores were made public before writing this postmortem. And, well, I was disappointed with my scores. But that also made me think hard about what my goals were, and to try to remember that the main goals are to just build something and have fun!
So, by that criteria, it was a complete success.
But… seeing the scores, seeing which games did well, really made me think about how to treat a game jam as a game design exercise. The winning games are generally very simple from a technology perspective, so all the cleverness is in the game design itself.
One reason I decided to use a lot of new stuff for LD41 was that I don’t feel proficient enough in Unity’s 2D toolset (which I’ve been using to build Moustachevania) or in any other game engine for it to be too much of a time advantage to use that, so I figured I might as well learn something new anyway. A lot of the people who enter Ludum Dare seem to be seasoned developers who are very comfortable with the technology they use, so LD is, for them, almost entirely an exercise in design and execution, with little to no part of it being about struggling with the tools or tech.
I don’t have a prescriptive takeaway from that. My advice is to just know what your goals and limitations are, and to try to build a game that fits within both. It’s just fine to fumble around in something new and build something you barely consider a game, and it’s also fine to pick up a technology you know incredibly well and can be productive with.
I won’t be able to enter the next Ludum Dare because it overlaps with the Outside Lands music festival, which I attend every year with my awesome wife. But LD41 will definitely not be my last game jam. It was a great experience, and I recommend it to anyone who builds or wants to build games.