Prototype 3: Break the Bank
Get it here for free.
OK so prototype three is finished, and honestly thank God for that. It’s been a very interesting lesson in the art of motivation and the dangers of underestimating the complexity of programming video game A.I. I realise this is also my most late blog post yet, fortunately the reason for it’s delay is my excitement for prototype number 4 which is coming along very nicely indeed.
So Break the Bank is a simple arena shooter in which you shoot zombies with a pistol until you die, or the game crashes. If a zombie touches you, you die. You may notice this is nothing like the concept I described a couple of weeks back. Well it turns out building a proper first person shooter with multiple guns, physics and AI based enemies is a really complex, time consuming challenge and I simply wasn’t motivated enough by the concept to do it.
Never the less I’m pleased with the results. I pared the design back to a zombie arena on Tuesday the 7th and was able to build that. Every zombie you kill (re-kill?) remains in the level and they stack up in fairly funny ways. The ragdoll effect was fun and I quite liked the music I ended up using.
(Again if the technical specifics of coding games doesn’t interest you skip forward to the design section)
Despite the reduced scope of the game I managed to add some interesting code to my ever growing repo of scripts. As the first game that had AI characters in it I had to begin to develop a series of classes for NPCs. At the moment I use simple inheritance with a parent NPC class and a child ZombieBanker class. The NPC class has the code for movement and dying in it (elements that I will absolutely need again in the future be it for friends of foes).
The ZombieBanker class contained the behaviour specific to the zombie characters in this game. They were quite simple. Upon spawning in they locate the player and move towards them constantly. There’s no detection code, they automatically know where the player is at all times. To move towards the player I had to get the vector of the difference between the zombie’s position and the player’s position and normalise it. This provided the direction the player was from the zombie, which was then passed to the move method.
The NPC class itself borrows very heavily from the ThirdPersonController I built for Torch Lighter (Yes reusable code!). All I had to do was swap out the reading for input on the joystick / WASD keys and use a provided Vector3 for movement instead. This allowed me to duplicate the Animation Controller from Torch Lighter as well saving me over a week of work. All I had to do was swap out the animations for walking and running to use zombie based ones from Mixamo instead, and voila hordes of marching undead!
The only other interesting challenge from a coding point of view was spawning mechanics. I had simple requirements: spawn the zombie in a random location and make sure they are more than x distance from the player. Nothing fancy in the solution here. I created a function that took a minimum Vector3 and a maximum Vector3 (essentially defining a cuboid of space in which the object can be spawned) then generated a random value for the x, y and z values between the minimum and maximum of each. I then checked how far that point was from the player and if it was too close simply ran the position choosing function again. Sooner rather than later a random position would be picked that was suitably far away then the zombie could be spawned there.
Designing and Building
As I said at the top it’s obvious that the final result here is very different to the game I had intended to build at the start of the two weeks. My intent was to build a very simple first person shooter level, think Goldeneye or Time Splitters. Looking back now that seems like a wildly lofty aim given the time scale and my experience coding both A.I and shooting mechanics.
I spent the first week trying to build that initial prototype. I added ray casted bullets, which would hit whatever the very centre of the screen was looking at. I then spawned a bullet hole at that point, which was pretty easy to get going and looked quite good. I then played around with physics, allowing the bullets to impart a force on anything they collided with, again very cool and quite simple.
The problems began when I started trying to add an enemy. Some would say enemies are a key component of First Person Shooters. These people would be correct. Sadly they are very complicated to get working. As per the coding section I modified the code I wrote for Torch Lighter to handle enemy movement and animation. I knew early on that I wanted to use ragdoll physics on the enemies the moment they died.
For those that don’t know ragdoll physics were a precursor to the more realistic complex physics and animations that games use today. The earliest game I remember using it was Hitman 2: Silent Assassin although I’m certain that was not the first. In essence various parts of the model (think forearm, lower leg etc) is given it’s own RigidBody so collides naturally with the environment. Each RigidBody is connected to another by the bones used by the animation skeleton. This provides a more realistic death animation and allows bodies to flop around post death (with often hilarious and morbid consequences).
Unity provides a very good wizard for creating ragdolls, simply requiring the creator to drag and drop various bones from the animation skeleton they already use. Unity then generates each of the RigidBodies and attaches them to the Game Object in question. Once the ragdoll was in place on the model (I’m sorry Torch Lighter you were the only one to hand) I added code to detect when a bullet hit an enemy which would then call the NPC.die method. This method told the Game Object to turn off the Animation Controller (that would select the animation for the living model be it run, walk or idle) and turn on the ragdoll. At the same time the bullet would impart a decent sized Impulse force to the ragdoll, making for interesting death animations.
That all worked great, the problem was that implementing just an animated static enemy that reacted once they got shot took me almost a week. It was a combination of burnout (Torch Lighter was a ton of work to finish up) and a lack of interest in the concept. I found multiple days going past in which I got no work done and realised I would need to alter the final game concept if I was to stand any chance of finishing on time.
I decided to go with Zombie enemies as all they needed to do was rush at the player. I added the code for that basic behaviour and enemy spawning (see the coding section above) over the last couple of days of development time then added in my usual menu and game exit components. This left with me with a very basic arena shooter which I was able to just about say I was proud of when I released it (a lot of thought went into saying “proud” in the menu, but I think that sells the prototype a little short).
I am pleased with the visual design of the game. I used a green fog effect similar to the blue fog used for the under water sections in Sunwalker Omega, which masked the zombies spawning in from no where. I also used a wonderful skybox that I stumbled upon when building Torch Lighter, making for a very green Turok 64-esque arena. Finally I put torches on each of the walls of the level, continuing my chain of callbacks to the previous prototype.
So what did I learn from my first failure of the year? I think the key word is passion. In order to work on something out of hours you need to be passionate about that project. I lacked a passion for Break the Bank and that is telling in the resultant game. There are first person shooter games I would love to make but clearly this wasn’t one. I was hesitant about the original intent of the game, and was keen to distance myself from the notion of violence against these “evil” bankers.
I make these games in my free time and I don’t have much of that. After a run in the evenings I have two, maybe three hours in weekday evenings and something like 24 hours over a weekend (assuming I have nothing else on). If I’m going to dedicate a reasonable amount of time to one of these prototypes (50+ hours) I damn sure better have a passion for the thing I’m trying to make or the motivation simply won’t be there.
A.I was an eye opener as well. I could probably have coded an enemy that shoots the player. That’s a far more complex task than it sounds though. Perfection is simple in programming. I code an A.I that hits the player every time without fail in under 10 minutes. The difficulty lies in making an A.I that hits the player when the player deserves to be hit, one that represents your typical poor movie henchman. Then you need code to detect the player, figure out if they are in line of sight, and how to get them in line of sight if they are not (but only if the A.I is aware). That’s two weeks of work alone if not more right there.
Beyond that I found asset selection a problem. I wanted to build a half decent approximation of a bank but found very few appropriate pieces of furniture or decorations available on the Unity Store (at least for free). I think I’m going to have to try and get back into 3D modelling if I want to build specific locations (something I’m encountering again on my new prototype), and then I need to start balancing my time between designing, coding, level building and asset creation. An interesting challenge I suppose if nothing else (anyone want to do 3D modelling for me? You get paid the same as me!).
All’s told it has been an interesting couple of weeks, I’ve certainly learnt a lot about myself, my motivations and I have some decent building blocks for NPCs which will be undoubtably useful for future prototypes! Bring on prototype number four!
Happy trails and I’ll see you down the road.