Harmonize: Looking back on a learning project


For the last 10 weeks or so I have been on a journey with the goal of learning a bunch of new things about game development, as I hope to make a shift into this field from my previous career as a front end software developer. Having gone through quite the interesting process, I am now writing this post with the hopes of sharing some of what I was able to learn with others who my be in a similar situation - maybe you also are interested in getting into game development, or ever are simply curious about how it works. If it can help at least one person learn something new and useful, then this post will have been a success.

Fair warning, this post is quite long. Either way, let's get started.

The Plan

Sometime around mid-January 2023 I decided that I wanted to see for myself what making a game is all about; in particular I wanted to get some experience in areas I had none of it. In the past I did dabble in game dev briefly over a couple of game jams, and in developing a game to test my hypothesis in my master's thesis, but all of these we simple projects where I mostly dealt with game design and programming, so I wanted to try my hand at other things, particularly creating and working with 3d assets, bringing together a more complex project inside a game engine and figuring out what exactly a shader is.

To that end, I decided to create a simple 3d tower defense game in Unity from scratch by myself, a project during which I would have the opportunity to learn about all those things and more.  The choice for 3d was a given, since I wanted to learn about the entire process of working with 3d; tower defense was chosen as a genre due to its relatively simple mechanics and understood formula which would not get me caught in game design choices or complex coding; and Unity was the engine of choice simply because it was the one most often listed as a requirement in job openings (around that time, in my context and location. Your job market experience may vary).

Having decided that I would not spend much time with game design (not because I am a good game designer, but because I was eager to learn other things), I started.

The Process

Fuelled by a sense of purpose and that giddy excitement of doing something new, I jumped into the Unity editor and started poking around to get familiar with it - my previous experience with Unity being very superficial only.

Coming directly from my previous professional experience as a front-end app developer, I took a brief detour to read up on software architecture and patterns suited for Unity projects, landing first on this ebook by Unity about game programming patterns. Going over some recommended patterns and briefly touching on useful concepts for code organization in a game project, the book was a valuable resource and a good, quick read, but looking back on it now I absolutely should have spent more time studying concepts such as these in order to better understand game programming as a whole. At the time however, I was all too eager to get moving to consider that.
After the first couple of days I had a basic scene set up with a minimal tower defense structure: enemies would spawn and move along a predefined path, and towers would shoot them. That was enough for me get started on something brand new to me: 3d art.

It is pertinent to note that the entirety of my 3d experience prior to this was stumbling my way through blender towards a blocky mug in a workshop some six years ago, so I was gonna have to start from zero. My primary resource for understanding what the hell I was doing were the very comprehensive introduction to blender videos by Flipped Normals, which I can thoroughly recommend.

Geode Carrier

Meet my first ever 3d character. He did not make the cut into the game, sadly

I could go on for hours about my experience learning 3d, but I don't think it would be very constructive or useful, so I will instead get right to the two major points I took from my time with it. First, it was a lot of fun. Modelling things and then bringing them to (clunky) life with animations was very fulfilling in a creative sense, which I can greatly appreciate. Second, it was a lot of work. Out of the project's ten weeks, at least five of them were entirely spent in blender, learning the ropes and trying things out and, eventually, creating the models that made it into Harmonize. Naturally someone with even slightly more experience at this than me would have achieved better results in a far shorter time frame, as much of my time was spent doing things wrong, learning the right way, then redoing those same things with all the expediency of a true beginner


Harmonize Final Models

Have you ever seen such a ragtag bunch of misfits?

Along the way, as I created the models and animations to replace the cubes and spheres that served as placeholders in my scene, I was also poking around with shaders, trying to learn what exactly they do and how they work, and how thy might make my poor models look a little more presentable. While writing shaders is technically programming, their nature makes them a very different kind of program than what I was used to, so there was a lot of groundwork to be done in understanding their functioning.

To explain my findings briefly, shaders are programs that run on the GPU and are primarily used to determine how the 3d scene should ultimately be rendered to the screen. In essence, each execution of a shader determines the colour of one pixel on the screen (or output texture, more generally), and thus shader code runs thousands of times for each frame. Being directly responsible for creating the visible render of a 3d scene, shaders can be tailored to produce different effects and results, such as applying custom light calculations, shifting colours on a material over time or even deforming geometry by "virtually" moving vertices before rendering them.

If at least five weeks were spent learning about and trying my hand at 3d modelling and animation, learning shaders and playing around with them made up the second largest time investment of the project, clocking at around two weeks and some change. I first made my way through HLSL and writing shaders as straight up code, before migrating to Unity's newer Universal Render Pipeline and trying out their Shader Graphs. Having gone through this process, I am glad I had the chance to experiment with both raw shader code and Shader Graph: learning about shaders through code made a lot of sense to my computer science major brain, while trying things out in Shader Graph allowed me to recognize a wider range of possible applications of shaders.

Lightning particles plus shaders

Using shaders with particle effects can offer some neat results

Overall, I am glad I got to learn a bit about shaders during this process, as I went from having no clue what they were or how they worked to realizing the incredible power they have, from creating the noise-based waves in the fog outside the map boundaries, through the shifting colours of the scenery crystals to the very cool (if I do say so myself) lightning effects of the electric towers.

At this point I was about two months into the project and, while I had learned a lot about 3d, shaders and putting things together in Unity, I was still far from having anything remotely looking like a game. I had a bunch of not-terrible assets and some fancy tricks to make them look better, but the game itself was very much barren, so I spent the final two weeks wrapping things up and going over the remaining parts I would need to get a functioning demo, even if a bare bones one.

The programming part of things, where I coded in the behaviour of different towers, the system which allowed the player to build them, the scripts responsible for spawning waves of enemies and also the ones that made sure enemies could be attacked and destroyed by towers - you know, making the game work - was, perhaps regrettably, very short. Having invested so much time already on other things, I felt like I had to quicken up the pace here. As a result, the code base of the project is ended up looking rather messy, and I did not properly assess the best ways to organize code and the proper architecture to employ.

Another part of the game which was thoroughly rushed was building the UI. I have worked with splendid UI and UX professionals, and I have taught students who were also amazing at this, so I know enough about the subject to be aware that I am terrible at it. Rather than dedicating sufficient time to learn more about the correct ways of putting together an interface, I instead built the whole thing on the last afternoon of the project, which meant I got to learn very little about it. At least I can say I had some practice with Unity's relatively new Input System. which was nice.

And then, it was over. Ten weeks had come and gone, and I knew I had to wrap it up or else I would just keep delaying it forever, so here we have it. Harmonize. The result of a somewhat haphazard ten week process with little direction beyond "let's learn some stuff". Soundless, bare bones Harmonize. And for all of its flaws, I am amazed that I was able to get this far.

While there is still plenty more to talk about; many struggles and achievements, things that seemed cool but turned out terrible, things that turned out cool but never made it into the game, and curious anecdotes from my time bashing my head against shader code, this post is long enough already, so let's move on to the...

Takeaways

For starters, it is evident that planning is always crucial. I knew that already, from my previous ventures, but this time I got caught up in the hype to get things going and thought I could just wing it. And while I did just wing it, I could have learned a lot more with a bit more careful planning ahead.

First of all, for saying that I am a programmer, I came out from this project with perhaps more questions than answers about game programming. Unity's Object-Component paradigm clearly favours an almost modular separation of responsibilities where complex behaviour emerges from the interaction of multiple components. What I failed to grasp was the adequate way of handling communication between these different objects and components and their integration. Should scripts hold references to other scripts, or should I prefer runtime lookups? Finding objects and components at runtime seems terribly inefficient, but having scripts that hold scripts and get linked to other scripts via the Inspector also seems like it would get quite hard to manage rather quickly. Furthermore, I was unable to fully make use of reusability in my code. For all the many interfaces I created early on, most of them ended up seeing little use, and many were just outright deleted at some point. Unity does not like having interface types in its Inspector, so the plug and play idea of having multiple different implementations under the same interface (say, like TowerShoot) becomes a little more complex than simply plugging and playing. This polymorphism was still useful in creating factories to instantiate composite objects, but I am sure there are much better ways of going about structuring code in Unity projects than what I came up with.

A second question that comes to mind when looking back at the project is regarding time allocation. Was the relatively large time investment into 3d and shaders justified, compared to the very short time for coding, UI and all else? In a real project with a real deadline, that would most likely be poor time management on my end, but for this learning experience I would say it was time well spent. Even if I do not plan on specializing in 3d art or anything like it, I am glad I got to learn about these things and achieve results that, while not groundbreaking, were quite satisfying given my total lack of skill or practice. I would also recommend that anyone looking to embark on a similar journey spend at least a little time on things you do not plan to specialize on - if nothing else, it will be useful when you get to work in a team to understand a bit of what your teammates are doing and the challenges they face.

Speaking of which, it is regrettable that I did not get to spend any time at all learning about working with sound for the game. That is another field I have approximately zero experience in, and it would be great to at least give it a try. Had I planned out my time better, I might have been able to fit some exploration into sound design and composition during this project. As it stands, however, that will have to be something to keep that in mind for future projects.

Ultimately, even with these and other issues, the whole process was immensely satisfying to undertake and a wonderful way to start taking all those long time ideas about game dev that had been living in my mind and turning them into actual, real actions. A small, timid start for sure - but a start nonetheless. I appreciate that my situation is uniquely advantageous in that I was able to work for a couple months full time on what effectively is a passion project, but I hope anyone reading this who also would like to try their hand at this can find some time to get started, even if just a little bit here and there. It can be an awesome experience, and hopefully just the beginning of something big.

What's next

Now that Harmonize is in a state I am content about, it is time to get moving. My next project is not a learning one - but an actual game to be developed to completion and published. One which I start on my own, but may very well end as a team effort. I will of course take the necessary time to think things through and plan out this new project, and there will be plenty more I have to learn along the way, so I hope to write many more posts here detailing this next journey. For now though, it's back to the drawing board with me. Thank you for reading through this sizeable stream of thoughts from this aspiring game dev - and hopefully I will see you in the next one!

Leave a comment

Log in with itch.io to leave a comment.