Friday Fun #1

Welcome to the first edition of what will hopefully be my blog done weekly. This is where I will share with the world my overall progress on my projects, as well as take some deeper technical dives now and then into a particular design that deserves highlighting.

Already for the last couple of months, I have been reporting progress on a daily basis on my Patreon, so if you want even more up-to-the-minute gory details of daily game development, make sure to subscribe and become a patron. This weekly blog will summarize, distill, transform, and augment what is reported in Daily Standup.

Prepare For Warp Gets a Release Date

First, I want to talk about Prepare For Warp as the project winds down. Prepare For Warp will leave Early Access for Full Release on August 4, 2022.

Two weeks ago, I took Prepare For Warp to the COGG meetup for some informal demo and playtesting. I received several remarks about how good the game looks graphically, which is a proud accomplishment for me since I come to game development with a very strong technical background and a less strong (but still present) artistic background. People are telling me, unsolicited, how graphically appealing the game is.

I also hit the mark strongly in another respect, as I received a lot of comments about the strong sensory experience of the game. I set out to create an experience that provides a bit of sensory overload, and I have succeeded.

Overall, I am very happy with where the game is, and just need to set aside some more time to complete playtesting. This playtesting will happen in parallel with Dehoarder 2 development.

Dehoarder 2: Keys to Success

With the Prepare For Warp project winding down, it is time to get back to work on Dehoarder 2. I’m shaking up the project in a big way. Nothing is sacred and everything is up for question in my quest to make Dehoarder 2 the great game that such a magnum opus deserves to be.

I sat down and meditated on what key factors would dictate the success of Dehoarder 2, and I identified six:

Build a Following

A game needs players, and I will need to actively seek them out.

Work within the Time Allotted

Nothing else means anything if I have to abandon this project to go back to a mundane full-time job.

Story

Storytelling is essential. The story experience of Dehoarder 2 must move you.

Moddability

Intrepid modders should be able to create their own experiences with the Dehoarder 2 core engine with few limitations.

Production Values

Graphical and aural fidelity are very important to story immersion and player experience.

Pushing My Boundaries

This one is a little more personal, but it refers to the positive feedback loop that exists where I accomplish something that is at the edge of my capabilities, and that provides the confidence and knowledge to further extend the boundary of my capabilities.

Dehoarder 2: Modding First

Of these keys to success, I decided to focus first on Moddability, as it provides strong synergy with and enables many of the other five keys. Moddability will help attract a community. It will help to keep the game modular, more maintainable, and thus less expensive time-wise to develop in the long term. It will enable story scripting in a more comfortable fashion that my current design. It will allow me to easily manage game assets and their quality. Finally, writing a world-class modding system would provide a technical challenge that pushes my boundaries.

I had always planned to have strong mod support, however, modding was not very well integrated into the game, and in the form I was trying to provide it, it couldn’t help but be limited, slow, and cumbersome in the end. From a technical perspective, what I am talking about is I had the beginnings of a system that could load individual image files and text files at runtime, but not much else. Unity provides little to no facility for importing new assets at runtime, and while you can hack in text files, a few images, and with a little work, sounds, doing so is very inefficient in terms of memory and performance, and importing anything else at runtime requires herculean development effort or a 3rd party software package.

So I decided to re-implement my mod system from the ground up, and in the process, rework the entire asset loading architecture of the game. Taking cues from the developers of Factorio, I decided to make the base game itself into a mod, and use Lua scripting to build the game database.

The new mod system is built around Unity’s Addressables system, which is pretty widely understood at this point. Since Unity lacks capable facilities for ad-hoc loading of assets at runtime, modders will need to use the Unity Editor to create and package Addressable Asset Bundles that will get deployed to a mod folder.

On startup, the game will load any “base” mods, as well as any player-installed mods that are configured as enabled. Each mod can supply a Lua script to register assets in the game’s asset database. Using the registration script, mods can add new assets, modify game database entries, and remap assets to use other, alternate assets.

The API exposed to Lua for managing the game database has been very deliberately designed to be easy and efficient to use, with fluent object building and as little complexity as possible. In fact, with a naive property-for-property conversion from XML to Lua, the registration scripts for the core game mod winds up about the same size as the old XML definitions, and there are a lot of ways I can reduce duplication now in those scripts that were not possible with XML.

Here I show a sample object definition from the game. Astute developers will note how an entire object hierarchy can be defined in one code statement, making for a very convenient object definition notation.

Some things might look a bit more complex than they need to be at first glance, with a closure creating the object, but it all makes sense in context of the larger design of the database building process:

This script will actually be run multiple times during database loading, so that mods can have an opportunity to modify database entries added by other mods. Factorio solves this by allowing mods to provide separate stages of load scripts, hard-coded to three stages. I decided to take a different approach, running the same script multiple times. In order to avoid duplicate initialization, I take advantage of a commonly used Lua idiom regarding singleton initialization of globals, the complexity of which is hidden behind the AddNewJunkTemplate() function. The end result is that the closure that actually creates the object will only run once, even though the entire script is run in multiple passes.

I’ve added some other cool features through this API as well. The database building API can actually detect whether a mod is “dirty” or “clean” (or as I prefer to term them, “transformative” or “additive”).

Even better, to manage all of the glue code behind the database building process, I leveraged code generation, based on a schema definition of my game data. So as I add and change the game database schema, the Lua API will automatically evolve to adapt.

All existing game assets have been migrated over to the new Mod system, and the old asset loading system has been completely removed. So I am now forced into using the same system I’ve created for modders, helping to guarantee that every feature that modders need gets exposed.

Dehoarder 2: Render Pipeline Upgrade

This section relates to the Production Values key to success. Up until now, Dehoarder 2 was still using the venerable Unity Built-in Renderer, whose support state is “pending obsolescence” if I correctly understand the position of the Unity team. So all cool, new features are going to come for Unity’s newer render pipelines first. Plus, the Universal Render Pipeline (URP) is known to give a modest performance boost, actually supports a proper post-processing pipeline that doesn’t feel like a hacky bolt-on, and supports other features I want access to like ShaderGraph.

Overall, the process of upgrading to URP went about as smoothly as I expected. I knew I was going to have a couple of surface shaders to convert, but it wasn’t a huge deal to re-implement those shaders in ShaderGraph, and it gave me some good experience with ShaderGraph. The biggest surprise was in how URP breaks the default shaders used with Tree Creator trees. It’s disappointing that Unity could not see themselves clear to upgrade these shaders, especially since someone else managed to upgrade those same shaders and is happy to take my money to give me working tree shaders (Though that package also has a few other URP shaders I am VERY interested in, like the hair, skin, and cloth shaders, so it was well worth the $25.)

After converting to URP, one of the first things I did was to re-implement my post-processing stack. Though I’m not finished, I managed to see a substantial improvement in visual quality.

You can see especially the ambient occlusion effect in the edges and corners, and the anti-aliasing. Less obvious is the Vignette, Tonemapping, Bloom, and Shadow/Midtone/Highlight adjustment.

I’m feeling inspired by how Prepare For Warp received so many comments on its visuals. It makes me more confident that I can make Dehoarder 2 look good. I will be continuing to see what I can do to improve the visuals of the game.

Before Post-Processing
After Post-Processing

What Next?

With Prepare For Warp shipping in less than a month, I will need to devote some time for playtesting and addressing any issues that arise. For Dehoarder 2, I will be continuing to enhance the new mod system, allowing mods to declare dependencies on other mods, adding support for custom scenarios, allowing the player to enable/disable mods, and adding better validation of database entries added by mods.

In the near future, the mod system will be further extended to allow objects to more easily respond to in-game events in a custom manner. This will likely involve the ability to set up Lua event handlers for things like collisions and interactions.

I’ve covered a lot this time, and this post has become quite long. I’ll go ahead and wrap it up here, and hopefully will be back next week with more news.