Matchmaking & Networking SDK
This guide introduces the Play SDK and explains how to integrate core multiplayer features into VIVERSE Studio content. It covers setup and usage for features such as matchmaking, session management,
BEFORE GETTING STARTED: you must authenticate with VIVERSE, including App ID creation in VIVERSE Studio, before requesting Play SDK services.
Initialize the `playClient` instance
Before using any Play SDK features, you must initialize the client instance. This global reference ensures that the Play SDK is available throughout your application.
Example Code:
globalThis.playClient = new globalThis.viverse.play();Matchmaking API
The matchmaking and networking APIs must then be initialized individually.
Example Code:
globalThis.matchmakingClient = await playClient.newMatchmakingClient(appId);
NOTE: Support for random and ticket-based matchmaking is under development.
Disconnect
Disconnect multiplayer client connection
matchmakingClient.disconnect();Setup Actor Info
Set the player’s session ID, name, and custom properties in the current room.
This API should be called before creating or joining a room. The SDK will store the actor information and automatically attach it to the player upon entering the room.
Example Code:
await matchmakingClient.setActor({
session_id: session_id,
name: name,
properties: {"level": 8,"skill": 8}
});
// Return values:
{
"session_id": session_id,
"name": "name",
"properties": {"level": 8,"skill": 8},
"is_master_client": false
}
//Failed Value:
{
"success": false,
"message": "error message"
}Setup Actor Properties
Update the player’s properties.

Example code:
await matchmakingClient.setActorProperties({"level": 8,"skill": 8, "team": "A"});
// Return values:
{
"level": 8,
"skill": 8,
"team": "A"
}
//Failed Value:
{
"success": false,
"message": "error message"
}Create & Configure a Room
Call createRoom() with a configuration object like so:

Example code:
await matchmakingClient.createRoom({
name: 'Casey's room',
mode: 'team',
maxPlayers: 4,
minPlayers: 2,
properties: {
"level": 13,
"skill": 21
}
});
// Return values:
{
"id": "a3c1f45e-ef7e-45b9-a0e2-60aea50dfc16",
"app_id": "app-29375017",
"mode": "Room",
"name": "Actor962's room55",
"actors": [
{
"session_id": "cc3d2a1c-34de-4b4e-9a57-f05ec6210b9c",
"name": "Actor962",
"properties": {
"level": 0,
"levelThreshold": 0
},
"is_master_client": true
}
],
"max_players": 4,
"min_players": 2,
"is_closed": false,
"is_game_started": false,
"properties": {},
"master_client_id": "cc3d2a1c-34de-4b4e-9a57-f05ec6210b9c",
"game_session": "a3c1f45e-ef7e-45b9-a0e2-60aea50dfc16",
"created_by_me": true
}
//Failed Value:
{
"success": false,
"message": "error message"
}Set Room Properties
Set the room’s custom properties.

Example code:
await matchmakingClient.setRoomProperties({"custom_value": "custom_value"});
// Return values:
{
"custom_value": "custom_value"
}
//Failed Value:
{
"success": false,
"message": "error message"
}Join Room by RoomID
Join an existing room by its room ID.

Example code:
await matchmakingClient.joinRoom(room_id);
//Return Value
{
"id": "a3c1f45e-ef7e-45b9-a0e2-60aea50dfc16",
"mode": "Room",
"name": "Actor962's room55",
"actors": [
{
"session_id": "cc3d2a1c-34de-4b4e-9a57-f05ec6210b9c",
"name": "Actor962",
"properties": {
"level": 0,
"levelThreshold": 0
},
"is_master_client": true
},
{
"session_id": "85733119-ef17-4cd5-a02e-421f16bb5c28",
"name": "Actor34",
"properties": {
"level": 8,
"levelThreshold": 8
},
"is_master_client": false
}
],
"max_players": 4,
"min_players": 2,
"is_closed": false,
"properties": {},
"master_client_id": "cc3d2a1c-34de-4b4e-9a57-f05ec6210b9c",
"game_session": "a3c1f45e-ef7e-45b9-a0e2-60aea50dfc16",
"created_by_me": false,
"playerCount": 2
}
//Failed Value:
{
"success": false,
"message": "error message"
}Leave Room
Leave the current room that the player has joined.
Example Code:
await matchmakingClient.leaveRoom();
//Return Value
{
"success": true
}
//Failed Value:
{
"success": false,
"message": "error message"
}Close Room
Close the current room. Only the room creator can perform this action.
Example Code:
await matchmakingClient.closeRoom();
//Return Value
{
"success": true
}
//Failed Value:
{
"success": false,
"message": "error message"
}Get Available Rooms
Retrieve the current list ofavailable rooms that can be joined.
Example Code:
matchmakingClient.getAvailableRooms();
//Return Value
{
"success": true,
"rooms": [
{
"id": "78e4c44a-4d3f-433c-820f-805c0b915dfb",
"app_id": "app_id",
"mode": "team",
"name": "Alex's room",
"actors": [
{
"session_id": "7dc0bf85-ff81-4bcd-907d-1ad35d4aad1f",
"name": "Alex",
"properties": {
"level": 24,
"skill": 90
},
"is_master_client": true
}
],
"max_players": 4,
"min_players": 2,
"is_closed": false,
"properties": {},
"master_client_id": "7dc0bf85-ff81-4bcd-907d-1ad35d4aad1f",
"game_session": "78e4c44a-4d3f-433c-820f-805c0b915dfb"
}
]
}
//Failed Value:
{
"success": false,
"message": "error message"
}Get My Room Actors
Get the latest list of all actors (players) currently in the room.
Example Code:
matchmakingClient.getMyRoomActors();
//Return Value
{
"success": true,
"actors": [
{
"session_id": "76192ade-5bb5-4937-835d-c936b7e9e6df",
"name": "Alex",
"properties": {
"level": 22,
"skill": 33
},
"is_master_client": true
}
]
}
//Failed Value:
{
"success": false,
"message": "error message"
}Start Game
The room master starts the game and notify all clients to begin. Room info update(is_game_started=true)
await matchmakingClient.startGame();
//Return Value
{
"success": true,
"message": "Room game start notify"
}
//Failed Value:
{
"success": false,
"message": "error message"
}Matchmaking Event Listeners
You can listen to matchmaking events using matchmakingClient.on(eventName, callback) . These events help you track lobby status, room lifecycle, and player activity in real time.

onConnect Event
Triggered when the client successfully connects to the SDK.
matchmakingClient.on("onConnect", () => {
console.log("SDK connected.");
});onJoinedLobby Event
Triggered when client joins the lobby.
matchmakingClient.on("onJoinedLobby", () => {
console.log("Joined lobby.");
});onJoinRoom Event
Triggered when the client joins a room.
matchmakingClient.on("onJoinRoom", (room) => {
console.log("Joined room:", room);
});
//Return Value:
{
"id": "5478c615-f067-4d1e-ba9a-ea44c628189c",
"mode": "team",
"name": "Jordan's room",
"actors": [
{
"session_id": "212187e3-a11a-4bbb-8325-9dafd895f1cb",
"name": "Jordan",
"properties": {
"level": 22,
"skill": 5
},
"is_master_client": true
}
],
"max_players": 4,
"min_players": 2,
"is_closed": false,
"properties": {},
"master_client_id": "212187e3-a11a-4bbb-8325-9dafd895f1cb",
"game_session": "5478c615-f067-4d1e-ba9a-ea44c628189c",
"created_by_me": true,
"playerCount": 1
}onRoomListUpdate Event
Triggered when the list of rooms in the lobby is updated.
matchmakingClient.on("onRoomListUpdate", (rooms) => {
console.log("Updated room list:", rooms);
});
//Return Value:
[
{
"id": "7c6fd350-2187-4a63-94ff-6955c40612da",
"app_id": "app-29375025",
"mode": "Room",
"name": "Actor488's room52",
"actors": [
{
"session_id": "035f6e43-e73c-4a08-aa5a-35662691928a",
"name": "Actor488",
"properties":
"level": 8,
"levelThreshold": 7
},
"is_master_client": true
}
],
"max_players": 4,
"min_players": 2,
"is_closed": false,
"is_game_started": false,
"properties": {},
"master_client_id": "035f6e43-e73c-4a08-aa5a-35662691928a",
"game_session": "7c6fd350-2187-4a63-94ff-6955c40612da"
}
]onRoomActorChange Event
Triggered when the list of actors in the current room changes.
matchmakingClient.on("onRoomActorChange", (actors) => {
console.log("Current room actors:", actors);
});
//Return Value:
[
{
"session_id": "035f6e43-e73c-4a08-aa5a-35662691928a",
"name": "Actor488",
"properties": {
"level": 8,
"levelThreshold": 7
},
"is_master_client": true
},
{
"session_id": "5079cf88-1f8e-470b-9513-54edb38188d3",
"name": "Actor183",
"properties": {
"level": 5,
"levelThreshold": 6
},
"is_master_client": false
}
]onRoomClosed Event
Triggered whe nthe room is successfully closed by the client.
matchmakingClient.on("onRoomClosed", (room : Room) => {
console.log("Room closed: ", room);
});onError Event
Triggered when an error occurs with a client request.
matchmakingClient.on("onError", (error) => {
console.error("Matchmaking error:", error.message);
});stateChange Event
Triggered when the client connection state changes.
matchmakingClient.on("stateChange", (state) => {
console.log("Connection state changed to:", state);
});onGameStartNotify Event
Trigger when the room master starts the game, notifying all clients to begin.
matchmakingClient.on("onGameStartNotify", async () => {
console.log("Game has started! You have been assigned to a room. Preparing to join the game!");
});Multiplayer APIs
Prerequisites
Before using any Multiplayer APIs, you must:
Initialize the Play client instance
Construct a
MultiplayerClientinstance with a valid room ID and app IDCall
init()to establish the multiplayer session
Initialize Multiplayer Client

Example Code:
//initialize multiplayer client instance
const roomId = 'example_room'; //obtained from matchmaking
const appId = 'example_game'; //App ID from VIVERSE Studio
const userSessionId = 'cutom_userSessionID' // optional, set user session id
// init options, optional
const options = {
'modules': {
'networkSync': { enabled: true, desc: 'networkSync description'},
'actionSync': { enabled: true, desc: 'actionSync description'},
'leaderboard': { enabled: true, desc: 'leaderboard description'}
}
}
globalThis.multiplayerClient = new globalThis.play.MultiplayerClient(roomId, appId, userSessionId);
const info = await globalThis.multiplayerClient.init(options);
//Return Value:
{
"session_id": "user_session_id",
"room_id": "example_room",
"app_id": "example_game"
"modules": [
{
"type": "network_sync",
"desc": "network sync description"
},
{
"type": "action_sync",
"desc": "action sync description"
},
{
"type": "leaderboard",
"desc": "leaderboard description"
}
]
}
Connection Control
Handles the multiplayer client's connection lifecycle. Use these APIs to detect when the client is ready and to manually disconnect when needed.
Connect Event
Triggered when the multiplayer client establishes a connection. Use this to perform setup logic after the session is ready.
Example Code:
globalThis.multiplayerClient.onConnected(() => {
console.log("Multiplayer client connected.");
});Disconnect
Manually disconnects the multiplayer client instance. Useful for cleanup or leaving the session before navigating away.
Example Code:
globalThis.multiplayerClient.disconnect();Client Connect Event
Invoked when a new client connects, allowing you to track who is currently online.
Example Code:
globalThis.multiplayerClient.onClientConnected(userSessionID =>
appendLog(`onClientConnected, userSessionID: ${userSessionID}`)
);Client Disconnect Event
Invoked when a client disconnects, allowing you to track who goes offline.
Example Code:
globalThis.multiplayerClient.onClientDisconnected(userSessionID =>
appendLog(`onClientDisconnected, userSessionID: ${userSessionID}`)
);General
The General module lets creators send and receive custom messages between peers in multiplayer scenes. Use this flexible channel when you need to define your own data format for syncing data, triggering events, or implementing custom game logic.
sendMessage
Sends message to peers.

globalThis.multiplayerClient.general.sendMessage(message);onMessage
Receives message from peers.
globalThis.multiplayerClient.general.onMessage((message) => {
console.log(`📩 onMessage: ${message}`);
});NetworkSync
This module synchronizes real-time position and entity state across players. This module is commonly used to update user or object positions in multiplayer scenes.
updateMyPosition
Sends my position request to the server.

Example Code:
const positionData = {x: 1, y: 2, z: 3, w: 4}
globalThis.multiplayerClient.networksync.updateMyPosition(positionData);updateEntityPosition
Sends entity's position request to the server.

const positionData = {x: 1, y: 2, z: 3, w: 4}
globalThis.multiplayerClient.networksync.updateEntityPosition('entity_id', positionData);onNotifyPositionUpdate
Triggered when a user or entity's position or state is updated in the scene.
Callback Payload: (data: NetworkSyncEvent)
globalThis.multiplayerClient.networksync.onNotifyPositionUpdate((data: NetworkSyncEvent) => {
if (data.entity_type == 1) { // User
console.log("networksync/notify_position/ update user: ", data.user_id, data.data);
} else if (data.entity_type == 2) { // Enity
console.log("networksync/notify_position/ update entity: ", data.entity_id, data.data);
}
});onNotifyRemove
Tirggered when a user or an entity is removed from the scene.
Example Code:
globalThis.multiplayerClient.networksync.onNotifyRemove((data: NetworkSyncEvent) => {
if (data.entity_type == 1) {
console.log("networksync/notify_remove/ remove user: ", data.user_id);
}
else if (data.entity_type == 2) {
console.log("networksync/notify_remove/ remove user: ", data.user_id ," entityId: ", data.entity_id);
}
});ActionSync
This module handles action-level communication and arbitration between players. Use this module when multiple players may trigger the same event (e.g. interacting with an object), and only one action should take effect — a process known as competition.
competition
Sends an action request to the server for arbitration.

Example Code:
globalThis.multiplayerClient.actionsync.competition(actionName, actionMsg, actionId);onCompetition
Triggered when a competition result is returned from the server.
Callback Payload: (data: ActionSyncCompetitionEvent)
Example Code:
globalThis.multiplayerClient.actionsync.onCompetition((data) => {
console.log("actionsync/competition:", data);
});
//Return Value:
{
"competition": {
"successor": "7794e184-9e3c-48f4-866d-9dc6e197ea42",
"action_name": "pickupExtinguisher",
"action_id": "4ac20fa1-a8a8-4b7a-90ad-571b89c6a10b",
"action_msg": "viverse",
"update_time": 1747645510990
}
}Real-time Leaderboard
This module handles real-time score reporting and live leaderboard updates across players during gameplay. Use this module to update a player's score and receive ranking changes in real time.
leaderboardUpdate
Submits a new score to the real-time leaderboard.

globalThis.multiplayerClient.leaderboard.leaderboardUpdate(score);onLeaderboardUpdate
Triggered when the leaderboard is updated and a new score ranking is available.
Example Code:
globalThis.multiplayerClient.leaderboard.onLeaderboardUpdate((data) => {
console.log("leaderboard/update_record:", data);
});
// Return Value:
{
"leaderboard": [
{
"user_id": "72f3a185-fbc0-4fdb-b64d-4e147de893e3",
"score": 92,
"rank": 1
},
{
"user_id": "a1c5faad-87ab-4b6e-a5e8-b9ae723fce78",
"score": 22,
"rank": 2
}
]
}Last updated
Was this helpful?