As a part of my masters course we were tasked of creating a short serious game designed to educate and teach the player in a specific subject as a part of a team.
We eventually settled on a first-person puzzle game designed to engage children aged 11 to 14 in logic gates which are core concept in low-level computing.
In the game the player takes the role of a digital robot being put through virtual challenges where they have to solve logic circuits to complete the game.
This is the presentation video used to showcase the gameplay of project to a class of my peers as a part of my grade for my masters course.
As a part of the development team for the project I had the most experience out of six of the team members in game development as well in the subject area, I was asked to take the role of project lead. I was rather nervous as this would be the first time I was ever asked to take direct lead in a project as before I often provided a more support role in any team I have worked with, but I decided to take on the challenge. With one of the first tasks being to organize how we would communicate with each other and divide tasks amongst each team member.
With this in mind I decided to approach this with the Agile style of development, assigning and discussing each team members task for the coming week which at the same time next week we would then sit down and discuss what we had managed to achieve, how far along they were in there task and if they required any assistance from any other team member in completing their task. To aid in this we set up both a whatsapp group which we could use to communicate when we were working remote, shared OneDrive folder which would allow us to exchange files, a GitHub to better handle version control of the project and an excel spreadsheet. On this spreadsheet was every milestone we had for the project as well as each task we needed to get complete for the end of each sprint.
Excel Spreadsheet used to keep track of what jobs needed to be done and by who during the project
When it came to start working on the implementation of the puzzle system, I originally started thinking about simulating the system within unity. Making use of trees and nodes to replicate the flow of power throughout a circuit. Going from one end of the tree to the other checking the supposed flow of power by checking the inputs of each gate as they received them to see if it would produce a powered output. However, in the end I decided to go with a different approach as the idea discussed above was simply not feasible within the time frame that the system needed to be complete. As a version was needed for the first milestone of the project, the prototype. So instead with some advice I decided to create a system that would simply check for the correct state of each piece. So, for example, for the first level we would check if both batteries were activated and if the slot base for the gate had an AND gate attached. We would then check the puzzle whenever any of these pieces had their states changed.
Then for the lights or wires connecting each piece we would simply check the state of the object they are “originating from” and if they were supplying power they would be set to on.
To explain this system, we will take level 2 as our example. During level setup we would place Batteries and Gate slots throughout the level. For each of these objects we would set the acceptable answer (enumerator variable) for each. For example, for batteries if they were connected to a slot where an OR gate would be placed, they would be set to check if they were in a state that would result in the OR gate producing a positive output. For gate slots we simply checked the gates type (AND, OR, XOR etc..) against the type of the acceptable answer
Older Version of level 2
Final Version of Level 2
Then within the scene that housed the level we would place a puzzle object into the hierarchy. Then within that puzzle we would pass it every piece to track the state of within the scene, so within level 2 we would pass it all four batteries and all three logic gate slots.
The scene would then be loaded upon awake with the game manager and puzzle manager objects as a singleton pattern as they stay consistent between scenes. Upon loading the new scene, the puzzle manager would find the puzzle object for the scene, which then the puzzle object would then pass all puzzle pieces that need to be checked for the puzzle to be complete. With the puzzle manager then storing these objects along with if they fir their own checks for being in a “correct state” for the circuit to be complete.
Each puzzle piece whenever it changes its power output to either off or on, by either being set by the player with the battery or having the correct gate attached to itself would then invoke an event in which it passes itself as a game object to the puzzle object which the puzzle will then use to determine if the piece is in a correct state or not for the circuit to be complete. It will then pass the object along with its current output to the puzzle manager where it will initially compare its output against its acceptable answer (being off or on), with which it will then update its dictionary of the object name and if it’s in the correct state or not for the puzzle to be completed
Extract from Puzzle Object Script
The Puzzle manager then checks this dictionary for if each object is in its correct state according to this dictionary and if so, the puzzle is complete and the door object will be told through an event to open its doors. However, for more complex inputs from batteries attached to gates such as OR or XOR in level 2 an additional check will need to be done.
During the puzzle completion check we check for any batteries that have a partnered object. Partner objects are other batteries within the scene that also feed into the gate slot attached to the battery objects within the scene. If a battery has a partner object it will perform a check according to both of their shared acceptable answer. For example, were the batteries to feed into a gate slot of a XOR gate they would check if only one of the two batteries are active.
Puzzle Completion Check
Battery Inputs and type Check
With the lights or wires also being tracked by the puzzle object within a dictionary, with a parent object where the wire would originate from and one of the connected wires from that object. Whenever the output of that objects power variable would be changed the puzzle object would have an event sent to it where it would look up the object within the dictionary and then pass the wires material to the puzzle manager to update its colour. Since we can change the colour of the material outside of an instance, we could update the material as a whole and update very wire object that shared that same material resulting the whole wire changing colour when power was provided from that object. With each material within that scene being reset upon changing to the next scene or level.
Wire lights activated based of output from originating object
Later, during development I would realise I had made a mistake, as many parts of each level could technically be completed by a different gate. So, for example there are both XOR and OR gates, where both these gates can be placed, these gate slots would both function with either provided gate. Resulting in a change to the system. Within the newer system the piece would have a list of acceptable answers. For example, both batteries and slot gate in the previous mentioned example would have an acceptable answer of either OR or XOR gates. The gate slot would then check the attached gates type against the acceptable answers that would provide am activated power output. Then later in the system the battery would check the type of the attached gate to the gate slot it was providing power to and check for the conditions that would provide that gate power.
The Game manager would then be used to keep track of if the game is changing scenes or if the game had been paused. If the game had been paused an event within a player pauser object attached to the player character would invoke an event to all listening objects which would then stop their updates based off the game has been paused or unpaused. With the game manager receiving this event and setting the game time speed of the project to zero.
Newest Pause Screen
Oldest Pause Screen
Then whenever the player were to leave the level through a trigger box entering the game manager would inform the puzzle manager and the puzzle object to empty all of their caches to reset for the player replaying the game and transitioning to the next level. So the puzzle manager was ready to receive the new puzzle objects within the new scene form that levels puzzle object.
Then later controller support was implemented through the use of the players actions being controlled through the new unity Input Manager. We would assign a function to both a key and a controller button and perform that function whenever that button was pressed. With the option to perform a small check in the main menu to check for any controllers that were not detected upon start of the game.