I didn’t get much done this week due to going out of town for a few days (first time since COVID began!).
Enemies have been disabled for the past several weeks while performing major refactoring. I re-enabled them this week and tested movement and combat. There were some new issues, which were easily fixed. There were also some old issues, which were also easily fixed because of the recent code improvements.
One of the techniques I’ve used repeatedly in the latest round of refactoring is game events. The event system I’m using is CSharpMessenger Extended. This has been a great way to decouple objects and clean up business logic. There’s no noticeable performance hit, but I am avoiding using events in code that runs frequently.
I added a text overlay that lists all enemies on the map and key attributes such as whether the enemy is active, if the enemy has previously seen the player, if the enemy currently sees the player, action points, etc. This has been helpful for troubleshooting.
Next week, I’m continuing to work through the bug backlog. I’m also considering changing pathfinding so that actors can’t move through walls on a diagonal.
I made a lot of “under the hood” improvements this week, including:
- Expanding testing configuration settings. In my ongoing effort to improve productivity, I realized that I needed a way to quickly reproduce and test specific features and objects. For example, there was a bug that allowed the player to take items in shops when the table the item was placed on was burned. I was wasting a lot of time reloading the map until a nearby shop appeared, then I had to find a fire potion that I could use to burn a table in the shop, and then walk back to the shop to reproduce the issue and confirm it was fixed. For this scenario, I added test configuration settings to increase the probability of shops and preload the player’s inventory.
- Centralizing testing configuration settings in a single GameObject. Different settings, such as fog of war, spawning enemies, and visual map generation, were spread across different scripts and GameObjects. I put all of these into a single GameObject so that I can quickly see what’s enabled and disabled and reconfigure test settings.
- Reusing random seeds for debugging. The game has the ability to reuse a random seed to generate the same map across multiple sessions, but I wasn’t using that feature much for fixing bugs. Capturing the random seed in my bug reports and regenerating the associated map has accelerated bug fixing.
- Automatic class and method logging. All game log writes are performed by a custom class. Using .NET’s handy reflection capabilities, I was able to automatically include the class and method that called the log write method. This has been very handy for tracing through sequences of events.
- Switch from binary to JSON serialization for saving/loading. I was using the .NET BinaryFormatter for serialization and didn’t learn until this week that the serialization method is now obsolete due to a security issue. Switching to JSON serialization was a quick and easy change.
- Overhauled script and Unity resource folder structure. There are currently 145 scripts and 175 resources. Over time, the original folder structure got messier and it became more difficult to find things. I was starting to guess in some cases where a particular script was located. Even a sub-second delay was a concern because that added up over time, in terms of time and mental energy. I created a new folder structure that is much better fit for the current file set.
- Many bug fixes, some recent and some long-standing. The bug backlog is finally shrinking, and after all the refactoring, there are far fewer occasions where I have to think hard about a solution; there’s now usually an obvious place for a fix to go and the fix is simple.
Next week, I’m adding enemies back to the map (they’ve been disabled for a while as I was focusing on other game aspects) to wrap up combat refactoring and close out enemy/combat-related bugs.