Devblog 25: Beetles! Economics!

Month Fourteen

When Jamie said “the internet is a mess and I hate it”, I suspected he wasn’t enjoying network programming. Frustrations regarding IPv4 versus IPv6 aside, he has completed the core networking task, and is happy for now. Unfortunately for Jamie, there’s more mess to it than that. Matchmaking with strangers over the internet is a different sort of thing to connecting with friends over LAN or WAN. But we’re in a good place now, which wouldn’t be possible without his hard work.

Speaking of hard work, we have more concept art: Michal has finished the first harvester. This beetle will run about the battlefield gathering resources for the player. I’m not sure if technically it is a crab… given how its claws look more like arms. Regardless, we are very happy with it.

When it came to the question of in-game economics, there are already a diverse set of examples in the RTS genre. As some of you may have guessed, the existence of a dedicated harvester implies that Command & Conquer (C&C) is an influence. But there are ways our design will depart from classic formulas to provide novel choices.

While there’s nothing wrong with Age of Empire’s villagers or StarCraft’s SCVs, I wanted an economic model which provides more opportunities for drama. The low cost and fragility of villager-type gatherers makes their untimely demise probable when the enemy shows up. In C&C, the question of whether the harvester will survive is more tense, because the harvester is more expensive, carries more resources, and is much tougher. The decision to create a harvester is more serious, and losing one is also a big deal.

However, if the player wants, they can task soldiers to gather resources. The downside of this is the aforementioned fragility, but also that a harvester would be far more efficient. The point of this choice isn’t to balance gather rates between soldiers and harvesters, but to provide the player with the means to do something if they don’t have access to a harvester.

Our design philosophy is about providing meaningful choice: players must be able to respond when things aren’t going to plan. C&C and AoE provide players with options when they start losing, and in both games you can run away and rebuild somehow: the map is a canvas upon which strategy is painted. That experience is dramatic and fun, especially when a comeback turns the game around. It feels natural to want to create a mutant hybrid from those two influences, and that’s exactly what we are doing.

Devblog 24: Meet the Androids

Month Thirteen

Jamie and I have almost completed our two largest challenges: networking and pathfinding respectively. The next tasks will be technically simpler, and provide the core gameplay loops necessary for a Real Time Strategy experience; base building, resource gathering, etc. Jamie’s work in particular has allowed us to finally upgrade our engine, from Unity 2019.3 to Unity 2020.2. This was because more recent versions of Unity removed their old network code libraries, which was something of a problem when we hadn’t a replacement.

Delightfully, the art pipeline has assembled. Our concept artist (Michal Kus) is delivering final concepts, which are handed to our 3D artist, while we look for an animator. So with this in mind, it’s time to reveal some of the soldiers you’ll be able to command!

From the start, I didn’t want a game which was constrained by realism. My love of science fiction is clearly showing, as I concluded that in a sufficiently advanced future there would be no vehicles on the battlefield. Why make a tank which has wheels? Legs are better. As such, each android soldier is the personification of a specific combat role. Amphibians are basic, mammals are fast, lizards are tough, and birds have long range.

These abstractions don’t make perfect biological sense (lizards can be very fast!), but I was inspired as much by the primitive power of anthropomorphic art as the idea that vehicles should walk. Considering that one of the oldest pieces of art in human history is the 40,000 year old ‘lion man‘, it seems that anthropomorphic art has possessed a spiritual significance for most of human history; inclusive of the famous animal headed gods of the ancient Egyptian pantheon. This design also allows us to make infantry types visually recognisable.

Of course, it’s all well and good to say let’s make a lizard man, but it is more difficult to know exactly how one should look. Over the last year Michal and I discussed and explored different ideas. There had to be a sweet spot somewhere between biological and mechanical aesthetics, and while designs which were less humanoid would be more visually distinct, they would also lose something of their humanity which is essentially functional. Perhaps you could say my inner Egyptologist won that debate.

Art will lag behind programming, but that won’t stop us from achieving our gameplay objectives soon enough.

Devblog 23: Blue January

Month Twelve

Jamie and I are back to work after a Christmas break. This means there isn’t much to report, but we have been making progress on lockstep, networking, pathfinding, and flocking. These systems are complex, and have proved challenging. It’s the most difficult work either of us has done. Nevertheless, we are fast approaching a basic completeness, upon which other functionality can be safely added.

It has been a year since work on the project began. Reflecting upon that, much has been done and much is still left to do. After we have finished the aforementioned concerns, the next tasks will involve the implementation of base building, economy, and art integration.

Other non-trivial tasks on the to-do list involve deterministic raycasting and computer player intelligence. The latter will be modelled on human attention and emotional states, so that the computer player behaves more like a human, providing a more interesting experience.

Devblog 22: Making Flocking Great Again

Month Eleven

This month Jamie and I were working together to make the terrain creation logic network ready. We encountered various problem which are typical of game development; the player intuitively expects everything to behave sensibly, but each sensible behaviour is actually a collection of many little pieces of logic which have to be strung together.

When it came to the question of how exactly do units create new terrain, the answer had to involve code to tell units to flee from the construction site before any work can begin. And that fleeing behaviour must itself be intelligible, units must flee the shortest distance to the nearest available safe space.

With Jamie left to mud wrestle network code, I returned to flocking. The most obvious issue was that groups of units suffered from jittery movement when they were close to an obstacle, be this another unit or a wall. The solution was twofold.

First, the order of execution changed, so that groups are ordered by distance from the destination, and then moved in that order. This increases the odds of units moving in the right direction, and thus moving with less jitter. If a group is told to move and a unit in the middle moves first, this causes problem because there is no space to move into. Second, after units have been moved by the flocking algorithm, their position is adjusted. This adjustment ensures that any movement into an obstacle is corrected immediately. The result was that jitter is less and group movement is smoother.

Another concern is ordering the impossible: when a player tells units to move to somewhere inaccessible. This could be because the player has told their units to move inside of or on top of a space they cannot reach, because there is no doorway or ramp to access that space. As it was, such an order would break the code.

The solution was to implement another part of Elijah Emerson’s flow field design. The map is composed of square sectors, but not all sectors connect. For example, if a player creates new terrain, the sectors on top and inside are inaccessible from the surrounding terrain. Each inaccessible group of sectors is stored as an ‘island’. Islands provide a useful metaphor, and enable much quicker searching to find the next best location units should move to.

Traffic jams also existed. The na├»ve solution is to find the fastest path to the destination, which works fine for individual units. But for groups this falls apart, because units begin to snag on corners, limiting the number who can move around a corner simultaneously. If the terrain didn’t have sharp edges this may not be a problem. The solution is to force groups to path down the middle of sectors, thus for the most part avoiding edges and traffic jams.

One of the last obvious additions will be to add a line-of-sight (LOS) pass to the process. This ensures that if the goal can be seen, then the unit will ignore the flow field completely and aim directly for the destination, which is the most optimal outcome. In order to efficiently calculate LOS Bresenham’s line drawing algorithm is required.

If all goes well, next week pathfinding will be relatively complete, and Jamie will have done the same with networking. That should put us in a good position before the two week Christmas break, prepared to begin the new year with refreshed enthusiasm.

Devblog 21: Lockstep and Two Smoking Barrels

Month Ten

When Richard told me that he needed “a Riker to my Picard to bring this project over the line”… well, how could I say no? Ever since I first played Metal Gear Solid 2’s demo I have been obsessed with gaming, and felt like I should attempt to make something. Since graduation in 2017 I have worked in software development. Experience as a programmer and later consultant allowed me to hone my skills, but recently, as everything certain has become uncertain, I felt it was time for a change.

With online multiplayer games it is important to make sure each player remains ‘in-sync’ with others at all times. This is where the Lockstep protocol comes in, it ensures that all players see the same actions taking place at the same time (within milliseconds depending on latency). Richard had already started implementation using John Pan’s lockstep framework, but it needed work.

During my first month this is where I focused, after spending a few days getting to grips with the codebase and Unity itself. My technical background was C# for web applications, so I knew the language, but the architecture was mysterious; much like the title of this post (a reference to one of the greatest movies of all time.)

After preliminary analysis the code looked abstract, all too abstract. So I began to, well, ‘rip out’ wouldn’t be far from the truth, lots of files I felt were unnecessary. Once I got the project building again I re-organised the classes into a legible folder structure. One thing to note here: If you’re going to move classes about, do it in the Unity editor, so that script references are not lost to game objects.

Joining player unable to ready up.

Once I was satisfied with a first pass it was nearly time to test. However, I had a few issues with the lobby and network code. For a start, players were not able to click the ready button to start the game. This proved to be a simple fix as the system was not treating joining players as humans.

Next task was to play a game, and to begin the cube wars. I discovered that the system was treating every spawn command as if it came from the host, this was easy enough to fix. But then it seemed that actions, whether to spawn a unit or move, were not reflected on the other players’ screens. This was somewhat problematic, had I missed something in the refactor? An investigation had to be carried out.

I began by taking it back to basics. I stepped through every line of code, from the spawn command until the unit appeared on-screen, I then compared the path the code took to other classes that I thought were relevant, in case there was a call to a secretive method. This was not the case.

My main mistake was assuming that the commands were being sent between players, examining code which looked very much like it received data packets. After a few days, and the odd existential crisis, I had a cup of tea and prepared to continue my war with the network code.

The entire British Empire was built on cups of tea. And if you think I’m going to war without one, you’re mistaken.

Eddy (Lock, Stock and Two Smoking Barrels)

Fuelled on tea and biscuits I had another crack at the code. I created a ‘SendCommandOverNetwork’ method which utilised Unity’s NetworkTransport class. Suddenly I was able to send spawn commands. “It’s all completely chicken soup” as Tom would say.

Synchronised violence.
Between angry geometric shapes.

Now I could finally get to testing. I had to be sure that commands were being executed by all players at the same time. Move commands had to take a similar amount of time to process and act upon, as this would be an easy way for players to become ‘out of sync’. I believe simple solutions are the best, so decided to log data to a .txt file, revealing critical information, like who sent the command and how long it took to execute.

I compared the logs, finding that one game was at least four seconds faster than the other. Yes, seconds, not milliseconds. Even after logging more data I was still not any closer to a solution. I then wondered, what if the Unity editor is just faster than the game builds? In hindsight, it did seem like an unfair test, to have one game build and the other within the Unity editor. So I changed the logging slightly, and had two game builds logging to separate files. You can already guess what I discovered, not only was the time of execution the exact same but the calculation times were pretty much equal, give or take a few milliseconds.

My first month was good, but I struggled with a few of Unity’s nuances, learning harsh lessons in the process. The transition from consultancy to working with a start-up on a game has been interesting. Work no longer feels like ‘work’, bugs are welcomed as a challenge to overcome rather than with distain or fear of missed deadlines. I am looking forward to the next challenge, which is of course more lockstep features regarding building, stances and overclocking.