29 minute read

Unto Deepest Depths is now out! Thank you all for following along on this game development journey, and extra thanks to those of you who picked up the game. As probably the last dedicated post to Unto Deepest Depths, I want to do a development post mortem today. I will not be discussing marketing or sales strategies because that’s not my focus or expertise, and there’s really nothing exciting for me to talk about there, anyways, but instead we’ll look at how the game changed over time, the challenges encountered along the way, and the lessons learned from making this game. Let’s dive in!

The game’s origins

To start, let’s talk about where Unto Deepest Depths came from, as this is not the game I was originally planning as my next Steam release. Instead, I had been working on a business themed strategy game for about half of early 2024 when I decided that it just wasn’t working and I needed to change directions to something else. Having already spent several months working on something that wasn’t panning out, I wanted something simpler and smaller in scope that I could verify quickly. While working on this other game, I’d started forming a vague idea of an ultra minimalist tactics game. Something that gets to the core of the genre while stripping out the stuff that would bloat the scope for a solo dev like myself. After a bit of brainstorming and iteration, I settled on an idea all about optimizing unit placement and throwing wrenches into that optimization, resulting in Unto Deepest Depth’s unique core rule of “All units must move and attack on their turn.” This prevents a player from finding the perfect spot and holing up until the enemy waltzes into attack range, makes friendly fire a lot more likely and dangerous, and adds a little bit of a puzzle element to the game while keeping it all straightforward and easy to pick up.

I got to work on a proof of concept and after about a month of working on the idea part time, I had twenty-five fixed levels one could play that proved the idea worked. I also had early versions of about half of the units and all five biomes that would be in the final game, so I felt confident this was something doable by just myself. So with the new game settled on, I shelved the old game and focused on this one fully.

But the game was still not what it would ultimately become, as those test levels weren’t just for the proof of concept. The game was originally going to be more puzzle and level oriented, with the primary gameplay experience being to beat pre-designed levels and unit configurations, unlocking the next level upon completion. The only procedural generation was maybe going to be some sort of simple battle generator you could play with as side content, where you could pick your units to play with and battle random units on one of the maps from the fixed levels. But with several levels in place, my focus for a while was on game flow and exploring the battle generator, and the more I worked on the battle generator, the more I felt it was where my focus should be. So, rather just shifting focuses entirely, I decided I would have a full roguelite mode of some sort with some fixed levels as side content. There are no fixed levels in the final game, though, as I ultimately decided that they just weren’t something that was worth putting time into. It wasn’t all a waste, though, as the fixed levels made it easy to verify the game design and the code involved for driving a level-based approach is still used to support the tutorial levels.

Game tech

On the technical side of things, Unto Deepest Depths does of course run on Godot, my go-to engine for many years now. Development started on 4.2, but the final game released on 4.3 despite the engine being on 4.5 by time of release. This is because I am generally hesitant to upgrade engine versions unless a critical bug has been fixed or there’s a feature that I need in a later version, which is rarely the case, whereas the introduction of new bugs or a change in how a feature works is much more likely during an upgrade. So I usually only upgrade engines in the first half or so of the development cycle, when the impact of a breaking change is relatively low and likely to be caught, and then stay locked to that version for the rest of development, hence the jump from 4.2 to 4.3 and no more.

The Switch version, though, is running on 4.5, as my publisher was in charge of that port and wanted to update the engine. For the most part, this just worked, but being on separate versions of Godot did lead to a bug in the game as how Resource duplication works changed in 4.5 (which is an issue in and of itself, but I digress). As pretty much all unit and player data are custom resources that make heavy use of duplication to function, this led to a game-breaking bug on Switch before release where units were completely broken. Thankfully, though, we caught it in time and patched it before release so everything worked out ok.

Speaking of the Switch version, it does, of course, have full controller support, and this is the first game I’ve made that supports controllers. I have played around with it a bit in the past, and I think there’s a game jam or two that has some light support for them, but it was a whole other deal to make sure the game is fully playable with a controller. Technically, supporting controllers is pretty simple with Godot since you can just map their inputs the same as any other, but practically speaking, you’re looking at spending a lot of time configuring focus neighbors and testing for edge cases, including hot keys that can sidestep the flow you’re trying to keep the player in. It got there eventually, but I did need to shift how I think about UI a bit.

To help with controller support, I used the Controller Icons plugin, which lets you make input prompts that dynamically change depending on what input method the player is using. This was very helpful to have and it saved me a good deal of time having to implement the same thing myself. Check it out if you want an easy to use system for dynamic input prompts.

Design dilemmas

Small numbers, big impacts

On the design side of things, once I had settled on the roguelite approach, the core gameplay didn’t change significantly from conception to release, but that doesn’t mean it was all smooth sailing. One of the things I’d settled on early in development was that I wanted to keep numbers small and any upgrades or stat impacts significant. For instance, most un-upgraded units have between one and four points of health and most enemies do one or two points of damage, so each time a unit is hit is impactful to the state of battle, and upgrading a unit to have an extra point of health can be the deciding factor between surviving another turn or not in future battles. Likewise, your can pump up the damage on your own units and dispatch with foes quickly before they have time to wear you down, but it may require more of a glass cannon approach where you’ll be running closer to a one or two hit death. I find this approach satisfying to play, but it was difficult to balance.

As XP is the only currency in the game, and it drives almost all promotion and upgrade choices, it had to be dialed in just right to make this approach of small numbers with meaningful impacts work, and the early feedback on the game’s demo was unanimous that I did not have it right. XP rewards were too low, upgrade costs were too high, and I didn’t have enough room for the nuance needed to get things dialed in as a single XP increase or decrease in cost could completely shift the viability of an upgrade, meaning the game was constantly swinging back and forth between too hard and too easy. So I ended up having to rework the XP system entirely. I doubled all XP values in the game and rebalanced from there, which let me get the nuance that the first attempt was missing.

Battle budgets

So while getting XP sorted out for units was challenging, a part of the XP system I’ve had from the beginning that I think works is the automated power scaling of battles based on the player’s progress. With the exception of boss battles, which are fixed instances I designed by hand, every battle in the game is generated via a point buy system, which works like this: Each enemy unit has a cost associated with it based on its difficulty relative to all other units - early game skeletons have a cost of two, for instance, while late game dark mages have a cost of twenty. Each world defines a pool of units it can draw from and their odds of being drawn, letting me tweak draw odds for the same unit across different parts of the game. Every time the player gains XP in the game, a value tracking their cumulative XP gain is updated. When a battle is being generated, this cumulative XP is fed into a function that returns a budget to be used to buy units for that battle. The battle generator then draws from the valid unit pool until it has spent its budget, places the enemies around the map, and that’s that.

From the beginning of development of the roguelite mode, this was my planned approach to procedurally generating battles, and I think it works pretty well. It certainly required a lot of testing and adjusting, but being able to say “Players think this section with a budget of 20 is too easy and this later section with a budget of 40 is too hard” gave me an objective way to look at the game’s difficulty and make adjustments. Of course, getting the costs of the enemies right was also quite the challenge, as was the modifiers that can be applied to the difficulty, such as the depth levels or player backgrounds, but in the end I didn’t find it a terrible way to get the balance dialed in.

Map design

Related to generating battles, something I’m more mixed on is the approach to map design. All of the maps in Unto Deepest Depths were hand designed, with the battle generator simply picking one from the pool of options and, on some maps, randomly placing traps or explosive mushrooms within the map to allow for some variance. The benefit of this approach is that each map was designed with specific consideration, but the downside is that making all of those map variations was a lot of work, and after a few runs through a given world the player may start to notice repeated map layouts. I debated this approach a fair bit, and did explore doing fully procedurally generated maps, but I just couldn’t ever shake the concern that the generator would mess something up, and in a game with punishing difficulty, losing to the map generator would be very unfair. I suspect that if I ever do a sequel to Unto Deepest Depths, I may spend more time exploring procedural options again and seeing if there’s a way to keep variety up while making sure things are fair.

Playertesting

Demo release

Let’s shift gears a bit and now talk timeline, specifically as it relates to playtesting and feedback. Unto Deepest Depths began development in June 2024, had a minimal prototype in July, and development shifted fully towards the roguelite approach around August. The game was announced in early September and the first public demo was released on Steam later that same month. The early days of development were a bit condensed as I wanted to have the game announced, and the demo released, in time for Steam’s Turn-Based RPG Fest, which started on September 30th, as I figured this would be an easy way to get a little early marketing going (spoiler: it did not, but that’s beside the point here).

To hit the festival deadline, I had to work hard to have the game in a state that was playable and polished enough to be releasable as a demo. Ultimately, though, I think I released it a bit too early. The balance was brutal (as discussed in previous sections), the visuals were a bit lackluster, and there were rough edges I knew already needed some work. Feedback, which came from a combination of social media, Discord, and a Google Form link embedded in the demo itself, was still generally positive, but it was clear there was a lot of work to still be done, which I knew. I suspect that spending even just another month or so on the game before releasing the demo would have allowed me to really get it into a good place and make a stronger first impression with it.

Despite this, though, I did get a lot of great feedback on the game, especially as it related to game balance. The demo lets you play through the first of five worlds in the game, so figuring out player expectations on difficulty and XP gain for the demo really helped to inform balance for the whole game, since I could assume that there would be similar expectations going forward. One of the simpler design lessons learned from the demo, which ended up becoming a foundational shift in how I balanced the game, was that people absolutely did not like having to wait more than one battle or event to earn enough XP to spend it on something. Feedback was unanimous that if the player gains XP, they should have the option to put it to use right away on something. Whereas I had previously been looking at XP as it related to upgrades at the world and game level, I had to shift my view to looking at it in terms of battles. “This upgrade takes two battles to earn, this one three, etc.” When I started doing that, it all started to feel “right” and like the upgrade balance was coming together. I made cost of the Helping Hand upgrade, which offers a conditional one time heal, tied to the XP earned in battle, that way you have the option to get it right away, if desired, and then planned the rest of the upgrades so that you were never more than one battle away from something on the upgrade tree. Whether or not a specific player wanted the specific item unlocked was irrelevant. This new balance meant that there was a constant flow of potential upgrades the player could get, and if they had their eye on something, they had a clear path to get it where every battle felt like a meaningful contribution towards that goal.

Playtesting

I continued to collect demo feedback through most of development before removing the link to the Google Form a few months before release when I felt there wasn’t much more benefit from demo feedback, instead shifting my focus to playtesting the full game. My partner and I did a significant amount of early playtesting and then I gave the game to a few friends to get their feedback. This let me catch some of the obvious issues with the game, such as major balance problems, bugs, etc, and then it was time to hand it over to playtesters who volunteered from my Discord.

The Discord playtest was really where the game came into its own. I thought the game was pretty close to release and only needed a few minor tweaks here and there, but the playtesters showed me just how much there was still to do on the project. So the month or so where the bulk of the playtesting occurred ending up being possibly the busiest time of the development cycle as I tried to quickly address feedback so as to not waste the playtesters time on a bad build, get as much feedback as I could on new builds, and to help keep the release to sometime in 2025.

It was during this time that a lot of the best additions to the game occurred. I overhauled or replaced several events in the game to make things more balanced and interesting, added the ability to place your units manually before battle - both increasing the strategic element of the game while also fixing annoyances with poor random unit placement, added icons for unit statuses and upgrades, added additional UI for the potential attacks of blocked units, fixed plenty of UI jank, and much more. This really was the time when the game came into its final form, so let me just take a moment to give a big thanks to everyone who playtested the game and shared such detailed (I really do mean detailed) feedback! You really were critical to the game’s development.

Final thoughts

And that’s a look at how development on Unto Deepest Depths progressed and some of the challenges encountered and ways the game changed over time. I’m proud of what I’ve made and feel I grew a lot as a game developer making the game. Thank you to everyone who has followed along from the game’s early days (and to those of you who read such a long post all the way to the end!). I look forward to sharing the next game with you as well!