Demonstrates how to use ARDK functionality to run a co-located networked multiplayer session where up to four players are localized in the same coordinate space and playing together.
The player is first prompted to select whether they will host a new multiplayer session, or join an existing multiplayer session by using a session code provided by the host. Once a player is connected to the session they will be prompted to localize their device’s position by scanning a visual landmark. After localizing, the player will be presented with a player list that displays the “yeti name” and connection state of each player in the session.
Once all players are ready, the host will begin the match.
The top of the screen displays a 45 second game timer and the player’s cumulative score: 100 points for each enemy firefly they hit with a snowball.
When time runs out, each player is presented with a score-sorted list showing who won the match.
ARDK Features in use:
ARNetworkingSceneManager- Manages the networked AR session.
ARPlaneManager- Manages detection of AR planes in each player’s surroundings
ARDepthManager- Provides the depth occlusion effect for occluding virtual objects. Utilizes the semantic segmentation system to suppress occlusion of objects that are on the ground
ARSceneCamera- Child of ARNetworkingSceneManager
ARNetworkingHelper- Helper convenience functions for managing the ARDK network session. Also wraps and relays ARDK network events.
SnowballFightDebugManager- Manages the debug functionality for the demo
State presenting GUI asking player if they want to Host or Join an existing multiplayer SnowballFight session
A UI displaying a warning about using AR; this is only displayed once per execution of the app, before the user enters an ARSession for the first time.
Host States - only for a player who is hosting a session
Displays instructions for how to host a multiplayer SnowballFight match. When the host presses the Start button in this state, the state exits and the ARNetworkingManager is enabled via the call to ARNetworkingHelper.InitAndHost. This method generates a random session code and enables the ARNetworkingManager. The ARNetworkingManager is managed using the Unity lifecycle, and it controls the creation of the networked session and the AR session. Transitions to StateConnecting.
Shows the host the session code that they have created.
If the host tries to start a session when they’re the only connected player, this state warns them that they will be creating a single-player session.
Join States - only for a player who is joining an existing session
Provides a text input field for a player to input a session code so they can join an existing session. When the player presses the Join Game button in this state, the state exits and the ARNetworkingManager is enabled via the call to ARNetworkingHelper.InitAndJoin. The ARNetworkingManager is managed using the Unity lifecycle, so this causes the creation of the networked session and the AR session. Transitions to StateConnecting.
Displays instructions for how to join and localize into an existing SnowballFight session.
Displays a UI graphic while the player’s device connects to the networked session.
If the player fails to connect, the application will show a timeout error and will allow them to restart the scene to try again.
When any player connects to a session, they must be acknowledged by the host to enter the session. Host peer acknowledgement is handled via a peer to peer message sent by the host in ARNetworkingHelper.OnPeerAdded(). This allows the host to enforce that only 4 players may enter the match.
If a player selects the option to join a session but then enters an incorrect code, they will become the host of their own session. If we detect this condition, we present the player with an invalid code error, and allow them to restart the scene to try again.
A player who successfully connects will network-spawn a PlayerBehaviour GameObject, which will manage their networked state in the session. The host will assign this player a name, which is stored in their PlayerData.
This state runs the process of localizing each device into a shared coordinate system, prompted by animated instructions. If the player is host, they find a visual landmark to localize the session onto - a shared physical anchor. If a Joiner, they have to find and localize using the same visual landmark and perspective the host used for localization.
During the localization process, the ARFeaturePoint helper is used to display feature point particles. This is done to guide the player towards feature-dense areas in an effort to assist with localization.
UI displaying a short “localization success” message.
Host and joiners both use this state, after either StateSessionCreated or StateLocalizationComplete. Displays a GUI with a dynamic list of current players (both host and joiners). Next to each player is an indicator showing whether or not they are localized and ready to start the game. GUI has a Start button to enter the game. If the player is the Host, and the only player in the player list, the next state is StateSoloConfirm. Otherwise, the next state is StateCountdown.
Displays a 3-second animated countdown before the match begins. Used by multiple demos including SnowballToss and SnowballFight.
The main game State in SnowballFight, in which the player throws snowballs at enemy fireflies and other players.
This state begins the enemy spawn logic. Each PlayerBehaviour regularly runs a method to select and suggest a good enemy spawn point based on the player’s current position and known ARPlanes. This value is set in that player’s local instance of their PlayerData, which is then shared across the session. The host uses these suggested spawn points to place enemies via the EnemyManager.
This state also activates the player’s NetworkedSnowballMaker, which will display the snowball toss UI button that holds/tosses 3D snowballs. Snowballs are created using a networked spawn, so they’re shared with all peers. When a local player tosses a snowball, their SnowballBehavior serializes and sends the toss data via message sent from SnowballBehaviour so that all snowball physics can be run locally on each player’s device via SnowballBehaviour.OnTossDataValueChanged().
Enemy collision detection logic is handled locally. Any instance that detects that an enemy is hit sets that EnemyBehaviour’s isAlive member false. This value change propagates to all peers so that they can locally run the enemy death animation.
When the local player hits an enemy, they increment their own score via PlayerBehaviour.OnSnowballHitEnemy(). Player scores are networked so that all players have access to the data.
The state waits until gameTimeAndScoreGUI’s timer is done.
UI displaying all player scores in descending order, and an option to Restart, or Return to Map. If restarting, the application returns to StateWaiting, continuing to use the existing ARNetworking session.
Editor-Only Mock Support
When developing ARDK applications in editor, to avoid always requiring building to a device, it is convenient to employ mock versions of AR assets that function in Unity Editor. Each scene’s mock objects are attached to the scene’s MockScene GameObject. This object has a MockSceneConfiguration component that will destroy the object if outside of Unity Editor.
This demo’s MockScene object includes:
ARDK VirtualStudio integration to fully mock a networked AR session. When running in Unity Editor, the local player is always the host of the session.
The ARMockPeerHelper, which listens for the mock session to connect and creates mock peers as specified in the ARVoyageMockPlayConfiguration. Each ARMockPeer handles spawning a PlayerBehaviour and listening for keyboard commands to run a simple simulation of having other players in a multiplayer match.
A MultiplayerArena that simulates a play space with ARPlanes
A MockMap that allows players to localize in the session