top of page
228777929_1022661068568607_4647833624211728305_n.png

The Story So Far

new profile pic.jpeg

Published August 20th 2021

So since I was a kid playing Playstation 2 games I've always been interested in the idea of game development. Ratchet and Clank was my inspo and I was always enchanted by not knowing how all this digital fluff made anything possible. I used to watch the game development records for stuff like Halo and Jak and Daxter, and knew that this was something I wanted to get around to. Fast forward past my degree in computer science and into the workforce, a group of my colleagues turned out to do a lot of game work on the side and this inherently re-ignited my interest.

 

The next question became where to start. A friend of mine is firmly concreted in the video game industry and has even worked with Insomniac Games (Ratchet and Clank creators). He once preached in a sagely tone something sort of like: "Don't be too ambitious, start basic and build it up over time". I promptly ignored him with questionable wisdom and decided to go for a futuristic semi-ambitious tower defence.

The idea came to me after I watched the Love Death Robots episode "Suits". Loved it. I immediately envisioned the idea as a tower defence with a comfortably short plot and all the nuances and mechanics that I'd need. At the time of writing this article I've some foundations done so I'm going to provide a re-cap. 

After having freshly read some software engineering books, which included Clean Code, I had a bit of a hard-on for inheritance hierarchies and code structure so I paid close attention to preparing the code in such a way that would be easy to refactor.

 

Second item on the agenda was to just have a prototype. A 'thing' which did a 'thing' kinda like the 'thing' I was out to achieve. 

236361207_358548512608268_3378428247325030865_n_edited.jpg

Now mind you, I can't really be bothered reloading one the earlier versions of the source code to grab you a nice crispy image, so instead you're going to have to enjoy a phone screenshot of video footage. But it had what we needed: some buildings, an enemy in the shape of a ball coming out of a mysterious dark tunnel, and the enemies on a trajectory to their goal. Sweet. Then suddenly towers.

227387578_972549753287827_6228207267283317795_n.png
221143597_1503763989973495_4384916794707300452_n_edited.jpg

I chopped together some primitives and had a lovely challenge setting the pivot point for the whole tower, and then getting it to appropriately aim at enemies. Eventually I got it working and came up with a little system of registering enemies it encountered and prioritising which one to attack - usually the one closest to the main base. This was the point I also had to re-learn how colliders worked but it all figured itself out.

 

It was at this point I started to realise how dynamically I'd need to track enemies and not with a fifo (First in first out) mentality. So I quickly configured to assign enemies an ID which was essentially my first optimisation in the code. It allowed me to track down an enemy in O(1) time because the data was more or less hashed. I couldn't envision more than 32,767 enemies existing at one time so I made the ID a short type in contrast to an integer which saves me two bytes on each ID.

232814842_350049900098667_6174678539138348622_n.png

Boom time for a map update. With the added bonus of tweaking enemy force to handle inclines and towers now apply damage and have a little flash gun effect.

234919674_1001047777380282_5348570850255545585_n.jpeg

Moving forward, source control was getting a bit out of whack. For those who aren't familiar, source control is a method of backing up your code to the cloud in such a way that you can easily handle the history of your code and other people can work on the same code in tandem. What I wasn't aware of how much change pollution Unity was producing in the background, so I had to customise my .gitignore file to make it so I was just handling what I was directly changing to source control.

 

Source control also brought to my attention that "Suits Tower Defence" as an acronym is unfortunately "STD" so I've had to take that one back to the drawing board.

 

You'll see in the following screenshot that the newly recorded set of changes for some recent-ish work I did has nothing near 500+ changes, so that's pretty swell.

237754705_127035049564006_5218174596272349614_n.png
237206982_3038140283130179_4704663092852824339_n.png

Did some one call for a map update and a glowing animated portal for enemies to fly out of? You got it chief.

235580000_519358609172803_5650055041584899381_n.jpeg

At the time I thought this map was sick, it's actually rubbish. This was my first time playing with Unity's terrain editor and there is an absolutely incredible amount of extra terrain behind this. In fact, for the longest time I just was working on this map relative to my camera's immediate scope, it wasn't until I tried to generate a height map of the terrain that I realised from the generated map, my terrain occupied about 1/200th of the planes actual size. But for now it'll do.

 

More complex geometry requires more complex path finding for the little enemies. So, really-easy-to-expand-on enemy paths were next on my to do list.

238548827_362593928791341_8615456357343824714_n.png

Essentially I just add nodes to the path and call them Path-x where x is the next increment and the path is constructed. After tweaking the enemies rigid body properties (physics), they actually glide around quite smoothly. This is really good because I intend on making their movement much more similar to water than a conveyor belt. Next up I wanted to expand on the player's experience, so some UI couldn't hurt.

227424298_2591371934493134_630240283926585553_n.png

Turns out it could hurt. Ew. I ended up removing all the crap on the top part of the screen and ended up with the bottom UI. It worked for the time being where the blue bar represented your tower's collective health and green represented your home base.

233718280_255815609709286_8710666109848982000_n.png

At this stage I noticed some odd quirks with performance. Unity does this dumb thing where it doesn't auto un-select game objects you've got selected when you run the project which has HUGE impacts on performance. But other than that, it turns out creating and destroying enemy entities was wildly expensive. Like o-m-g expensive. So after talking to some colleagues they more or less said "W-wait. You haven't implemented object pooling?". "No, my game involves no swimming pools gameplay mechanic?". So then I implemented object pooling and performance was great again.

 

Object pooling is essentially creating a 'pool' of a large amount of entities (in our case enemies) at the start of the game. Then instead of creating a new one, it utilises one that already exists. Vice versa when one would usually be deleted, we just disable hide the enemy ready for re-purpose.

231844343_373839854140807_236146031357424584_n.png

Did some one just say update that map? M-okay. I got a bit better at the Unity terrain editor and came up with this fantastic thing. Unlike our previous map, it is 1/1th a map ;)

234636463_156343726626836_8060886911931638567_n.jpeg

From here I noticed that the path wasn't perfect and unless I made it spot on the first time around, the terrain would get bumpy and gross if I was only using the same tools to soften it manually.

238620189_3083838161940430_7234583549595744981_n.png

And it just gets worse.

237851839_2958298997746571_2025574410951829375_n.png

And worse.

238374338_160958696150625_416078142710906523_n.png

And then I stumbled upon the terrain editor's softening tool and my god it was exactly the deus ex machina I needed.

236232959_999327570642256_1303560735756066879_n.jpeg

So by this stage I'd done additional code re-structuring - putting my new found clean code knowledge to work -, optimised performance, tweaked enemy and tower performance, did some UI work, and created a start-up animation for the portal. Stuff was okay. Then we got to the bane of my bloody existence. This next step has been the bottleneck of my progress for literally months.

 

I was on a mission to get some user functionality into the game and the next step was having a grid overlay on the map that I could place towers on. The more I thought about it the more I realised that this was an insane feat. If this had been 2D, no worries in the slightest. If this had been just a flat square for a map, too easy. I unfortunately had a complex terrain mesh and I thought for ages.

Bouncing ideas off of people, no one really knew what to do, and videos online only really demonstrated this effect for flat terrain so I was pretty stuck. I tried placing the grid squares by hand, that was a joke. I wanted to make it dynamic. Then in my head appeared a memory of my lord and savour, Sebastian Lague.

So Sebastian is a coding freak of nature. Like the guy is truly an expert. His videos on terrain generation, biomes and clouds, teleportation, they're all flawless. In particular his terrain generation video stood out to me. He used perlin noise to generate a height map which influenced the shape and design of his terrain. We didn't need to go that far but we could utilise the part of his tutorial that involved creating a mesh from indicies. My big plan was to make one in a groove of the map then have that as my intractable component.

So I got to work.

235884368_2920156741538134_7380772290420069236_n.jpeg
236784852_401326638010610_4833014522482960734_n.jpeg

The above hieroglyphs discuss the idea that for a given terrain, a grid of indicies will descend down then connect between themselves to mirror the terrain. The more points, the more like the terrain the replica will look. So I decided to give a frequency a value of 2^f so that relative to our frequency value, the detail would double. The secret to the difficulty of this setup is deciding how many points will reside in the matrix. (Retrospectively, having a moderately detailed map that wasn't too abstract and not too complex would have been ideal for comprehensive tower placement. If the frequency was too high, the tile borders would just be wiggly. :S)

If the width and height are the same, easy, it's a square. 2^f across by 2^f down. But what about if it's a rectangle?

236199769_840759880147061_1482901723263683780_n.jpeg

After a deliberation and a dash of algebra to help simplify what I came up with , I manage to figure out that the shorter of the width and height is 2^f in length, and that the longest is Floor( ( H( 2^F + 1 ) ) / W ) - 1. What this does is identifies that 2^f+1 is how many gaps will be on the shorter end. Then we understand how based on the width we can discover the length of each gap between the indicies, which would help us figure out how many of those gaps we can fit along the longest length; we then floor it to create a clean limit and maintain square distance between points.

 

Finally, we now have how many gaps of the longest length, we simply reduce by 1 to figure out how many nodes it'll be.

234561758_547746099684334_7577104394685166228_n.jpeg
231555703_158518226398244_790257293485757912_n.jpeg

Sweet. We have a nice example of generating a grid of varying sizes. As we can see, even though it's rectangular in volume, the nodes are squared in their separation. Below we experiment with lowering the nodes onto the map keeping in mind to avoid collision from the towers fields then play with the frequency to see how detailed we can make it.

238595093_957610591637826_6042604966841164332_n.png
219216458_297370688812726_3441516115388992235_n.png
236217028_143947761146547_181399104591596096_n.png

So this is more or less where I am at, at the conception of this blog. I'm starting to feel replicating the terrain for the sake of cell selection isn't the practical way ahead. Instead, maybe using the cells as indicators for grid tile dimensions, with each tile having its own collider; that way I can raycast from the mouse to select them. Even then it's going to be jenky because due to the terrain our square design may not play out as smoothly as we wanted. More of that in the next blog.

222445639_521657892237862_4284189714558701785_n.png
231098183_165801638959732_4109501876191389519_n.png

© 2023 Martin Brown, All Rights Reserved.

bottom of page