Aaaaand We’re Back!

Okay, so the past few months have been crazy for a bunch of reasons and that meant I couldn’t (or, honestly, didn’t want to) update the blog as much as I would’ve liked. I think this goes to show the previous weekly blog format was way too bloated so I’ve been working on a new - shorter - one. However, the radio silence doesn’t mean there are no updates. I did lose a couple weeks of programming time but I still managed to make a ton of progress. So, we’re coming back with a bang with a milestone entry.


The Story So Far

Quite a bit has changed since the previous weekly update; last we left off:

  • I was about to finish work on the “Divide” action, which was the last of the basic actions. All other basic actions (Movement, Merge & Camp) were done. Actions are essentially “abilities” that units can perform.

  • I had just recently finished work on the Morale System which allowed units’ morale to increase and decrease based on certain conditions. This code was written in a “code drunk, refactor sober” kind of way, so it was a bit messier than necessary.

  • UI was being a pain to work with, we were using the legacy UI system as a placeholder and it was causing a lot of issues that had been solved in the newer UI/Canvas.

  • Input management was being complicated, since logic was spread thin across the entire codebase.

  • I was facing a lot of issues with the structure of the project.

  • Planning/organizing/scoping work and tasks was proving to be an issue. I was routinely encountering issues with distractions, unclear scope for features and unrefined cards which was leading to progress being slower than intended.

  • The code-base was messy and unmaintained which was leading to issues with updating, refactoring and adding new features. This was just getting worse with every new feature we introduced and card we completed.


How it’s going

So, during the past couple months I’ve put my head down and gotten to work. It’s taken a lot of refactoring and flexing of my DX muscles but now:

  • The morale system has been completely revamped. In the previous iteration we weren’t using the C# type/class system for handling morale modifiers or consequences - instead, using lambda expressions and dictionaries which was far from ideal. Now we have introduced interfaces for each of those things and we have a single, self-contained class for each of them.

  • We have 100% switched to using the new UI system so there are no legacy (ugly-as-hell) windows/popups anywhere in the game. Every button, window, panel and UI component is now it’s own prefab and we can easily customize them from the editor (rather than from code). Even though everything is still using default/placeholder sprites, this means that switching it up and modifying it will be way easier in the future. This has also allowed us to centralize all UI logic into a single place (the UIManager) which was an opportunity to review old code and remove a lot of UI-specific code from other managers.

  • We have also made the change to the new Input system and centralized all input logic into a single class InputManager. The new event-driven API has made adding and modifying functionality a breeze and it should also allow us to easily support other control schemes aside from keyboard & mouse. Again, this allowed us to remove a lot of old code and review how we were handling input logic.

  • The structure/organization of the entire project has been completely overhauled and we’ve also gotten rid of old/legacy “stuff” that was hanging around for no reason.

  • We have added support for Testing (UnitTests, IntegrationTests and E2ETests). It took a while to get the hang of because documentation for testing in Unity is severely lacking (which is kind of worrying) but I got it working in the end. Having tests has allowed me to follow my regular TDD workflow - which has incredibly improved my organization, planning and scoping (I think you’ll see that in a bit). We’ve gone from 0 to 150 tests in about one month, which is a pretty good sign already. Introducing testing revealed issues with tight-coupling between components so, that lead me to the next point…

  • The entire game now uses Dependency Injection (DI) via Zenject. I know this is a contentious topic among Unity/C# devs for some reason but, implementing this helped in quite a few ways:

    • It highlighted inter-dependencies across Managers which allowed me to improve the code structure and logic further and clearly apply the SRP.

    • It helped isolate components for Unit Testing (which is an easy way to kickoff features and tasks).

    • It helped on creating abstract interfaces, factories and Managers for making code cleaner and less couples. For example, it aided in refactoring the morale system into cleaner code.

    • It was another opportunity to review previously written code, get rid of unnecessary bits and separate code more clearly.

  • We’ve cleared up naming conventions. This is pretty minor but it will help in the future when communicating and even writing code.

  • We’ve correctly applied the SRP: making every class/object/code/function as small and simple as it can possibly be (but not any smaller than that). Every manager now takes care of one single thing and it’s the Input, Phase and UI manager that compose all of that functionality to build the gameplay.

  • We’ve gotten rid of magic string/numbers across the entire codebase, everything is now a constant which allows us to easily modify values in one single place.

  • How armies are spawned into the game (specially at the beginning) has been completely changed. Were previously we had to create instances of the a prefab in unity and place them were we wanted them to be on the map; now we can specify the entire starting setup for the game in a single JSON file. This will allow us to easily implement save game later down the line.

  • Tiles, Unit Types, Paths and Highlights have all been converted from prefabs/classes to scriptable objects. This allows us to reduce memory usage during gameplay as well as to easily add and modify all of those things without the need of touching any code.

  • Bugfixing has also been a big one now that we have tests to debug and to add regression tests (in order to ensure we don’t fall back to the same bug later down the line). We’ve fixed about 10 bugs that ranged from mildly annoying to game-breaking.

  • Other note-worthy things:

    • We’ve settled on win/loose states as well as a secondary mission functionality.

    • We now have a mathematician helping out with a bunch of algorithms that I hacked together (and had no logic behind them).

    • We’ve also prepared a new blog format that is shorter, faster to write and easier to follow.

    • We’re working on getting some gifs ready for sharing!

    • We’ve performed plenty of research on conscripts and volunteers during the Spanish Civil War.


Features

  • All basic actions have been implemented.

  • The morale system is 100% done and working (it was pending a few modifiers and consequences before).

  • We finally have an “undo” button!

  • Locked unit logic has been revamped and distanced from “boolean blindness”.

  • All squads now have an indicator of how much Energy they have remaining.

  • We’ve introduced 17 new unit types.

  • Each unit type has it’s own action/ability, we’ve defined them all, prioritized them and completed work on 2 of them.

  • All units in the game are now “real people”. Before members of a squad were just number (ie: this squad contains 150 infantry units); now, those numbers actually represent human beings, so those 150 infantry units have names, nicknames, nationalities, political affiliation, religious beliefs, families, etc…


Whats Next

We got a bit “side-tracked” these past few weeks with the entire refactor - even though it was really necessary. What remains for the current goal of “completing the vertical slice” is:

  • Implement remaining unit-specific actions.

  • Add Missions and Objectives.

  • Add building functionality.

  • Add “City” logic.

  • Add “Reinforcements” logic.

  • Add “Logistics” logic (railways, roads and air/land/sea transport).

  • Create non-battle-specific morale consequences.

  • Add two special unit types: “Spies” and “Aircraft”.

And that should be it! Once that’s done, we can move on to AI (which is the bit that actually scares me the most since it can make/break a strategy game).

With all that said, I’ll see you on the next weekly update!

Previous
Previous

New Entry, New Format

Next
Next

Only YOU Can Prevent Nerd-Sniping