When a group of curious scoundrels open up a chest belonging to Pandora, they are surprised to find themselves cursed to play a series of party games intended for the gods. The onslaught of changing rules and competitiveness drives players to compete against each other in a myriad of unique challenges.
Engine: Unity
Team Size: 7 people
Project Length: 4 months
Role: Programmer
Focus: Tidal Sweepers creation, Kracken's Carnage AI
Contains only my scripts
Each minigame that needed more setup than the basic PlayerCharacter script offered had its own custom controller, and Tidal Sweepers was no exception. Since the players didn't need to move or jump, and they only needed to hit their action button to fire, the CurlingPlayerController set all of that up. It also appropriately assigned the player colors to the characters and their respective UI based on the player's ID. Whenever it's a certain player's turn, they have 5 seconds to line up their shot before the background coroutine automatically fires it for them.
The Round Manager, shown in the first embed (left), handles the overarching game. Each time the game loops back to the first player, the manager calculates the two team's scores, resets the positions of moved game objects, and prepares the area for the next round. The manager holds a static singleton reference of itself, allowing other scripts to call its functions and read its necessary variables required for resetting the gameplay loop.
The Round Handler, shown in the second embed (right), deals with the smaller details the manager does not need to handle. It holds many more specific variables that control team-specific needs. After the second player in the team moves, it swaps the active team's booleans with the other's, activating them and disabling the first until the next loop.
The puck's functionality is made up of three scripts: Power, Aiming, and GizmoAngle. The power and aiming script mainly control the UI elements that the player interacts with. Power is a slider bar ping-ponging from 0 to 1, and when the Power event is fired by the player, it grabs whatever value the slider is currently at and sends it to the GizmoAngle.
Aiming was a lot more complex with the intended motion. The two reticles spin and overlap at a central point, which required ping-ponging with the targets' sine and cosine values. When the Aiming event is fired by the player, it takes the distance between the two reticles and sends that value to the GizmoAngle. If the player hits it perfectly, the reticles flash white and a more impactful sound effect plays to signal their success.
GizmoAngle is where everything all comes together. It calculates how much force the puck receives, and it adjusts the aim angle to make sure it doesn't go flying behind the player. Once those final calculations are made, it sends the puck off! After the puck stops moving, it uses the Round Handler's methods to reset its team and prepare the next team's puck.
Many of the scripts needed references to animation and audio triggers. Instead of manually grabbing instances of the needed components in the individual scripts, a static singleton instance of the classes held all needed instances for every other script. In the case of the audio manager, its variables were public as well, not only to assign appropriate audio files in the inspector but to plug those variables into its methods. Whenever a script needed to play a sound effect during a certain action or it needed to trigger an animation, it could easily grab it from the managers.
After Tidal Sweepers was solidified, the next script needed was a pathfinding script for the minigame Kracken's Carnage. The premise of the minigame is that players would have to hide from a hunter among clones of themselves. The clones wander aimlessly around the map following a navmesh and an array of nodes placed on it. Each clone selects a random node to pathfind to, and once they get close enough, they choose another node to travel to. When a clone passes over a node, regardless if it is their target, they check that node off and put it in a separate list for later. After all nodes have been checked off, they refill their original list, clear out their checked nodes, and start the process over.