Hustle Hobo - Dev Blog #003 : Indicators / Logic-based state check
While playing Hustle Hobo, we faced issues with clarity and instructions. The game itself is based on a balance of dynamic interaction and precise interactions, meaning that the player can interact with things in many ways- but only specific interactions will progress the game. The game was simple once understood, but lacked instructions. We wanted to explain to the player how the game world works, but we didn’t want to hold the player’s hand, or use explicit tutorials. Our solution to this was to implement bubble indicators, directing the player through relatively subtle imagery. At first we placed individual indicators onto every prefab and area that needed an indicator, then coded each indicator to only display itself when the specified requirements were met. This worked well for gameplay, but was terrible for development because it didn’t allow for expansion without hardcoding more indicators. After trashing the design and code for those indicators, we decided we needed to implement some logic-based state checking. Logic-based state checking was a quick system that I implemented into the indicators. These state checks consisted of three scripts; Decider, Confirmer, and Combiner. However, using these three scripts we were able to reproduce all and more of what our previous indicators were capable of. Previously we needed to check a variety of states within the game, such as the player’s currently held item, or a specific item holder’s state to make sure the indicators were only visible when appropriate. With the new system in place, the developer/designer is able to place an indicator, then specify the appropriate parameters using a series of public bools within the Unity Editor itself. No coding required, only logical setting up of scripts. Decider(s) > Confirmer > (Combiner) Decider
The way the new logic-based indicator systems work is that you can add any amount of Decider scripts to an indicator, but each Decider can only accept one bool state (such as playerIsHolding), followed by an item filter (such as Flask or Grimoire), and an optional item state (Air Potion, Fire Potion, Enchanted, etc), where both filters are represented as enums. Confirmer
After adding the Deciders, a Confirmer is required to compile all the Deciders and if all are true, the indicator can be displayed with any assigned sprite. These two scripts alone make up the majority of our indicators, but some special indicators have more than one state that activates it. Combiner
Since Decider and Confirmers can only work with one specified state, a Combiner was implemented to handle And/Or logic using two or more Confirmers. To distinguish different Decider/Confirmer states, a new GameObject can be parented to the Indicator to contain the second Confirmer and its’ Deciders. The Combiner will then grab all Confirmers and check if their newly created public bool “combiner” is true or false. If combiner is true, the Confirmer not activate when all Deciders are true, but will instead tell the Combiner that its’ requirements are fulfilled. Using a public enum, the developer can then choose if the Combiner should use And or Or logic for compiling its Confirmers. Admittedly, this is the first time this system has been executed by the team, so the design is rough and not the easiest to explain, but its functionality is extremely successful. The Decider scripts appear long because they don’t use any kind of loops or shortcuts for state checking- but each check is usually no more than a single-lined if statement. This means that if we happen to need to add more states to check, we can simply jump into the script and add a simple if statement; making the new check an applicable option to all indicators in the game. Carrying on with this system, I would definitely attempt to simplify it and make it much more user-friendly in the Editor. I also feel this design could be easily transferable to other games for other purposes, such as checking states to trigger scripted story events, or applying dynamic logic mechanics to a sandbox game. Overall the design could use some optimization, but the use of this design fulfilled our needs very nicely.