Each system was designed to have a specific set of responsibilities, and to know about other systems as little as necessary.
Overview
- The PlayerDataManager assigns PlayerData objects to each player who enters the world.
- When a PlayerData object enters the Start Gate Checkpoint, the Course they just entered starts tracking their time, and activates the next Checkpoint.
- When the PlayerData object passes through the last Checkpoint, their time is added to the Scoreboard.
- If the PlayerData object enters a PowerUp trigger, the PlayerModsManager temporarily changes their speed and/or jump abilities, resetting them to default after a set duration
- If the PlayerData object enters a Respawn trigger, the Course will respawn them at the last Checkpoint through which they passed.
The following sections describe the programs and scripts that combine to make the whole experience.
Players
Each player who joins the world gets a 'PlayerData' object to manage their state and progress through a course. The PlayerDataManager assigns PlayerData objects, which can trigger OnPlayerDataEnter programs.
PlayerDataManager
You can find this program on the "PlayerDataManager" GameObject under the "Udon" object in the scene. It has two important public variables: dataPool: Reference to the VRC Object Pool component on the same object as this Manager. When a Player Joins the world, this manager will TryToSpawn a PlayerData object for them, and give them ownership. followCam: Reference to the camera that will follow above a Player as they run through the course. Set here so the PlayerDataManager can assign the reference to each PlayerData object when they are refreshed.
When you change the 'Number of Players' option in the Toolkit Window, all the existing PlayerData objects will be removed from the scene, then new copies of them will be added as children of the PlayerDataManager. Each one will have its public variables set up properly, and the Object Pool will be updated to hold all the new PlayerData objects.
PlayerObject
The PlayerObject prefab has a Rigidbody and Capsule Collider component, which are needed to trigger PowerUps, Hazards, etc. It's on a custom layer CoursePlayer which only collides with CourseTrigger to interact with Hazards and PowerUps. It also has an UdonBehaviour with an important program on it:
PlayerData
This program is the main connector between the player running the course and all the other systems. Its variables are: timeElapsed: Synced Float which is updated by the Course program when they cross the Finish Gate. When it changes, the owner of the PlayerData object will show this time on the scoreboard so they can see their latest time locally. The owner of the ScoreManager object will see this change and add the new time and displayName of the Player to the scoreboard.
isRacing: Boolean which is set true by the Course when the player has entered a start gate. It's set to false when the player enters a finish gate, manually respawns using their menu, or Reset is called on the Course. Used by the Course, see that program for more info.
rigidbody: Cached on Start by the program, it doesn't need to be set in the inspector. It's moved to the position and rotation of the player during every Update.
player: Reference to the actual VRCPlayerApi object of the local player. Cached when the synced playerId on this program is changed. Used to retrieve the displayName of the player.
timeDisplay: Reference to the UdonBehaviour which displays the latest time for the local player.
scoreManager: Reference to the ScoreManager UdonBehaviour. When the owner of that object receives a timeElapsed change from a PlayerData object which just finished the course, it sets the public variable scoreToProcess on the ScoreManager object to a string which combines the displayName and elapsedTime into a single string to be processed.
scoreManagerObject: Reference to the GameObject which holds the UdonBehaviour with the ScoreManager program. Needed to ensure we only run the Score Processing logic on the owner of the ScoreManager object. We can't get this GameObject from an UdonBehaviour reference, so we include it here.
followCam: Reference to the CinemachineVirtualCamera which follows the player around the course. The program sets its own Transform as both the follow and lookAt targets for the camera, and changes the priority on this camera when isRacing changes.