Hello, it’s Chantelle again! I’d like to talk a little about making tools for Dead Exit in Unity which made the game development process so much quicker and easier for us.
In our previous game, The Living Dungeon, players can roll dice or use a card to play an action. There’s only about 20 different actions so when it came to coding it, it was a manageable task to create a separate state and logic class for each of them. But in Dead Exit there are over 130 unique actions; survivor and vehicle cards have three separate actions each, plan cards have two, and resources, events and stop cards each have one, and the majority of these share the exact same behaviours. This posed a problem, because while creating 130+ states is not totally infeasible, it could take a really long time to build each one, test them and then maintain them. That’s pretty impractical.
So we broke down each action into different generic steps; for example a step could be selecting specific cards or players, shuffling a deck or moving cards. These steps would do the exact same thing regardless of which card played them, but chained together would result in a different action being performed. In total, we had about 30 generic steps which provided a much more practical solution when we came to build the logic!
When we had figured out how we wanted the actions to be handled, the next thing was how the data for each step was going to be stored. For this, I use a single class called StepData which has a bunch of variables to define the step. Then I have a ScriptableObject called ActionListData which has an array of StepDatas. From a data structure perspective, this is a totally fine solution and works exactly how we want inside the game. But actually adding the data to these lists was going to be a horrible task. To look in the inspector at a step was just a jumble of data, some of which is necessary to the particular step type, but a lot of it wasn’t and confused what data would be used in the action implementation. This is because, like I mentioned earlier, the StepData class is essentially just a container for variables which can be accessed by all steps, thus the inspector displayed everything.
I needed to figure out a way to make it easier to create and modify the action data in the inspector. So my first attempt was to create a property drawer for the StepData class. Property drawers can be used to customise how data is displayed in the editor, so I thought it might be a good idea to control which variables were displayed depending on what step type the StepData was set to. This way, whoever was modifying the data would know which data was relevant to the step type in in order to work correctly in the game. While that aspect of what I wanted did work, it also created new problems; the step data was stored in an array, so usually if you right-clicking on an element it will allow you to duplicate/delete it, but the property drawer interfered with this and made it useless in trying to move or insert new steps. In the end, the property drawer just wasn’t sophisticated enough for what I wanted and was still visually very difficult to navigate. I prefer to use property drawers for smaller custom variable types, which is something I wouldn’t describe the StepData class as. Back to the drawing board.
Finally, I tried making a completely different tool. I hadn’t really dabbled with creating editor tools before in Unity, but working on this tool has completely revolutionised how I use them now! I’ve created so many since making this one because they are so incredibly useful! The tool is a dockable window, which uses serialized properties to modify the data inside the scriptable object. It takes the action data asset (an instance of the scriptable object) and displays the step list depending on which action you select via a GUI.Toolbar. It has buttons on each step in the list to duplicate, delete, move up and move down, and each step only displays the relevant data for that type (an obvious solution I reused from the property drawer). A few of the step types are actually used in pairs, such as “Start Loop” and “End Loop” which behave the same as a for loop in code, so to make it easier to visualise where these occur in the step list, I indent the steps and display some curly brackets; something impossible to do in a property drawer, but as a coder I personally find immensely useful to mentally process what my action list is doing.
This tool has been incredibly helpful in handling the actions, but I’m probably just biased because of how proud I am of creating it. Nowadays when we’re testing Dead Exit and we find a bug in the way a card is played, it’s usually an issue with a single variable inside the step data, and thanks to this tool it’s incredibly easy to pinpoint and fix exactly where it’s happening. Prior to making this tool, I did struggle with the idea of where I could possibly need to create a tool to help workflow in Unity, but now I see so many possibilities. You’ll probably find if you’re struggling to handle data or are doing the same task over and over again, creating a tool will save you so much time in the future that it’s definitely worth investing some time into making one.
If you have any questions about making tools, game development or Dead Exit, please ask us on Twitter or Facebook! I love helping other devs out! You can also check out our Youtube, where you’ll find videos of myself doing some work logs, Graham doing some artist stuff (way above a coder’s head), and some testing sessions with the rest of the team!