Refactoring of the core systems continued this week. I thought I’d be done by now, but I keep finding new opportunities to better organize code. The biggest classes are shrinking, replaced by smaller, more focused classes and interfaces. The GameManager is down to 1,300 lines from 2,000. I’m still a bit hazy on what this class will ultimately do, but it’s clear that most of what it currently does needs to go somewhere else. Some examples of refactoring done this week:
- Simplified modal window management. Originally, each UI modal window GameObject was statically added to the scene in the Unity Editor. Each time one of these windows needed to be displayed, its contents were updated and it was made visible. When the window was no longer needed, it would be hidden again. This necessitated some complex state management, complicated input handling, and had a limitation of only being able to use a window once within a sequence of UI interactions. I created a manager class for modal windows that stores the windows in a stack. The window GameObjects are now instantiated when shown and destroyed when hidden.
- Reorganized player input handling. Player mouse and keyboard input handling was fragmented across the code. Input was handled differently based on the UI state. I had a lot of issues with mouse input in particular, for example clicks triggering events that were supposed to occur sequentially in different frames at the same time. I added an interface to the modal windows for input handling and implemented pertinent input handling in each window class.
- Simplified UI state machine management. A finite state machine was woven into the GameManager class to manage player input and modal windows. This made troubleshooting UI and input issues difficult. Organizing player input handling by modal window and simplifying UI window management eliminated the need for the state machine and greatly simplified the logic.
- Manager classes for enemies and cell effects. All objects in the game that act on their own, such as enemies and cell effects, need to be tracked separately from the rest of the game objects so that they can act in each turn. These were originally stored as lists in the GameManager, with methods in the GameManager class to manage them. I created a manager class for enemies and another manager class for cell effects, and moved the lists and methods into those classes.
The level of refactoring I’m currently doing would have been a lot more difficult to do had I focused on content creation instead of systems and mechanics. I’ve made a lot of changes to systems that have required changes to each object using that system. If I had had 100 objects instead of 5, this work would have been much more time-consuming. Adding content is tempting to do; it’s fun making new things. But, if you focus on content creation too early on, you may, at best, limit your ability to refactor efficiently or, at worst, end up with a game that is difficult to fix and enhance. For beginners, as I was with Unity, I strongly recommend building a “vertical slice” of the game before adding a lot of content and a lot of object-specific code.
Next week, it’s more of the same. I think I’m two weeks out from completing the major refactoring. Once this work is done, I’ll close out the remaining bugs and get back to the ever-growing feature backlog.