Using PlayCanvas with MassiveRealm
PlayCanvas is a popular open-source 3D game engine for the web.
You can use MassiveRealm with PlayCanvas to create multiplayer games.
Getting started
Check out our Quick Start Guide to create a new MassiveRealm project and get your API key.
Prerequisites:
- Create a new MassiveRealm project.
- Your project's URL and Public Key will be sent to your email.
- Create Logic entry.
- Create Room entry with alias
game
.
MassiveRealm Server Setup
This demo demonstrates multiplayer implementation with MassiveRealm.
Try the demo:
https://playcanv.as/p/jgHYeDcY/
Client-side source code:
https://playcanvas.com/project/1204880/overview/multiplayer-with-massiverealm
Server-side:
https://console.massiverealm.com/account/project/4094-e43c-4dbf
Step 1: Create Model
Navigate to the Communication > Models
section in your project's logic and create a new model called Player
with the following fields:
id - String
x - Float64
y - Float64
Step 2: Create Server Command
Navigate to the Communication > Server
section in your project's logic.
Create a new command called UpdatePosition
with the following input parameters:
x - Float64
z - Float64
This command will be called by the client to update the player's position.
Add the following code to broadcast the player's position to all clients.
We're using cluster: true
to broadcast the message across all locations in the Massive Cluster
let data = {
id: $session.id,
x: $params.x,
z: $params.z
};
// Use cluster=true to broadcast message across all locations
$session.broadcast(
'UpdatePlayer',
{
player: data
},
{
cluster: true
}
);
Step 3: Create Client Commands
Navigate to the Communication > Client
section in your project's logic. Here we will create 2 commands:
Command 1: UpdatePlayers
Input Parameters:
players - Type: "Model: Player"
Command 2: DeletePlayer
Input Parameters:
id - String
Step 4: Hooks
Navigate to the Communication > Hooks
section in your project's logic.
Hook 1: OnRoomLeave
Broadcast a message to all clients when a player leaves the room.
We're using cluster: true
to broadcast the message across all locations in the Massive Cluster
$room.broadcast(
'DeletePlayer',
{
id: $session.id
},
{
cluster: true
}
);
PlayCanvas Client Setup
Connect MassiveRealm Script
- Open your PlayCanvas project.
- Click on the
Settings
tab. - Click on the
External Scripts
tab. - Add the following script URL:
https://cdn.massiverealm.com/js/v1/client-browser.js
Like this:
Networking Script
Create a new script in your PlayCanvas project called Networking.js
.
Here is the example code:
var Networking = pc.createScript('Networking');
Networking.attributes.add('accessPointUrl', {
type: 'string',
title: 'Access Point URL'
});
Networking.attributes.add('publicKey', {
type: 'string',
title: 'Public Key'
});
Networking.prototype.initialize = function() {
this.app.networking = this;
this.joined = false;
this.client = new window.MassiveRealmClient.Client({
debug: true,
url: this.accessPointUrl,
publicKey: this.publicKey,
autoReconnect: true,
autoReconnectMaxAttempts: 3,
autoReconnectTimeout: 3000,
// Room configuration, exported from Room > Export in the Console
roomConfig: {
game: {"serverCommands":{"UpdatePosition":{"id":10,"params":[{"name":"commandId","type":"uint8"},{"name":"x","type":"float64"},{"name":"z","type":"float64"}]}},"clientCommands":{"DeletePlayer":{"id":10,"params":[{"name":"commandId","type":"uint8"},{"name":"id","type":"string8"}]},"UpdatePlayer":{"id":11,"params":[{"name":"commandId","type":"uint8"},{"name":"player","type":"model:Player","array_of":"model:Player"}]}},"models":{"Player":{"params":[{"name":"id","type":"string8"},{"name":"x","type":"float64"},{"name":"z","type":"float64"}]}}}
},
onConnect: () => {
console.log('Connected');
this.app.fire('GameRoom:clearRoom');
this.client.joinRoom({
// Room Alias as defined in the Console
alias: 'game',
// Use room id to join a specific room
id: 'room-1'
});
},
onReconnectTry: (retry) => {
console.log('Trying to reconnect', retry);
},
onDisconnect: (error) => {
this.joined = false;
console.log('Disconnected', error);
this.app.fire('GameRoom:clearRoom');
},
onJoinRoom: (roomAlias, roomId, isForwarded) => {
console.log('Joined to room', roomId);
this.joined = true;
// To notify other players that I have joined
this.app.fire('GameRoom:joinRoom');
},
onError: (error) => {
console.log('Connection error', error);
},
onCommand: (command, data) => {
console.log('Command received', command, data);
// Add a new player to the scene or move if existing
if (command == 'UpdatePlayer') {
this.app.fire(
'GameRoom:playerUpdate',
data.player.id,
data.player.x,
data.player.z
);
}
// Remove player from the scene
else if (command == 'DeletePlayer') {
this.app.fire('GameRoom:playerDelete', data.id);
}
},
});
window.addEventListener('beforeunload', () => {
this.client.disconnect(true);
});
this.client.connect(true);
};
Networking.prototype.UpdatePosition = function(x, z) {
if (!this.joined) return;
this.client.emit('UpdatePosition', {x, z});
};
Project Settings
Optimization Tip
Storing room settings on the client side may significantly reduce network traffic. This way, the client will not need to request the room settings each time it joins a room.
Navigate to the Rooms
section and select the room you want to optimize. Then click on Export
on the left side and copy the code.
Paste that JSON into the client-side code, and you're done!
More Performance Tips.