# Rooms Co-Play
Rooms Co-Play lets players discover and play Instant Games together inside Facebook Messenger Rooms — Facebook's group video calling feature. When a player launches an Instant Game from within a Room, everyone in that Room can join the same game context at the same time and play together in real time during the video call.
This guide covers what Rooms Co-Play is, how it works from both the player and developer perspectives, the SDK APIs you need to integrate, and best practices for building great room-based gameplay.
## What is Rooms Co-Play?
### Overview
Facebook Messenger Rooms let people start group video calls with friends, family, or communities. Rooms Co-Play extends this experience by allowing participants to launch and play Instant Games together during a Room session. The game appears as an overlay or dedicated view within the Room, and all participants who join the game share the same game context.
From a player's perspective, the flow looks like this:
1. A player is in a Messenger Room video call with one or more other people.
2. The player (or any participant) opens the games menu within the Room.
3. They select an Instant Game to play.
4. The game launches for that player, and other Room participants are invited to join.
5. All participants who join are placed into the same game context and can play together in real time.
### Why support Rooms Co-Play?
- **Social engagement:** Players are already in a live conversation with friends. Adding a game gives them a shared activity to play together during the call.
- **Discovery:** Rooms Co-Play is a discovery surface. Players who have never heard of your game can encounter it because a friend launched it during a Room.
- **Retention:** Players who play together are more likely to return and invite others to play again.
- **Differentiation:** Rooms Co-Play lets you offer a real-time multiplayer mode that is distinct from asynchronous challenges or turn-based play.
## How it works
### Player experience
When a game is launched in a Room, the following happens:
1. **Game launch:** The initiating player selects the game from the Room's activity menu. The game loads in the Room interface.
2. **Join prompt:** Other Room participants see a notification or prompt inviting them to join the game.
3. **Shared context:** All players who join are placed into the same game context (`ROOM`). Each player runs their own instance of the game client, but they share a common context ID that your game can use to synchronize state.
4. **Video continues:** The video call remains active alongside the game. Players can see and talk to each other while playing.
5. **Players can leave independently:** Any player can stop playing the game without leaving the Room. The game session continues for remaining players.
### Developer perspective
From a technical standpoint, a Rooms Co-Play session is a specific type of game context. When your game is launched inside a Room:
- The context type is `ROOM` (as opposed to `SOLO`, `THREAD`, or `GROUP`).
- All players in the Room who join the game share the same context ID.
- You can use the standard Instant Games SDK context APIs to identify connected players, send updates, and manage the session.
- Your game is responsible for implementing the multiplayer logic — the platform provides the context and player connections, but game state synchronization is up to you.
## Integrating Rooms Co-Play
### Detecting the Room context
The first step in supporting Rooms Co-Play is detecting whether your game has been launched inside a Room. Use the `FBInstant.context` APIs to check the context type.
```javascript
// Check if the game is running in a Room context
const contextType = FBInstant.context.getType();
if (contextType === 'ROOM') {
// The player is in a Rooms Co-Play session
console.log('Playing in a Room!');
initializeRoomMultiplayer();
} else {
// The player is in a different context (SOLO, THREAD, GROUP, etc.)
console.log('Context type:', contextType);
initializeStandardGameplay();
}
```
You can also retrieve the context ID, which is shared among all players in the Room:
```javascript
const contextId = FBInstant.context.getID();
console.log('Context ID:', contextId);
// Use this ID to group players into the same game session on your backend
```
### Identifying players in the Room
Use `FBInstant.context.getPlayersAsync()` to retrieve information about other players who are currently in the same game context (i.e., other Room participants who have joined the game).
```javascript
async function getOtherPlayers() {
try {
const players = await FBInstant.context.getPlayersAsync();
players.forEach(player => {
console.log('Player ID:', player.getID());
console.log('Player Name:', player.getName());
console.log('Player Photo:', player.getPhoto());
});
return players;
} catch (error) {
console.error('Failed to get players:', error);
return [];
}
}
```
**Important:** `getPlayersAsync()` returns the players at the time it is called. Players may join or leave the Room (or the game within the Room) at any time. You should call this method periodically or at key moments (e.g., at the start of each round) to get an up-to-date player list.
### Handling multiplayer game state
The Instant Games SDK does not provide a built-in real-time multiplayer synchronization layer. You are responsible for synchronizing game state across players. There are several approaches:
#### Option 1: Use a backend server
For real-time multiplayer games, the most robust approach is to use your own backend server (or a third-party service like Photon, Nakama, or PlayFab) to manage game state.
```javascript
// Example: Connect to your multiplayer server using the context ID
async function connectToMultiplayerServer() {
const contextId = FBInstant.context.getID();
const playerId = FBInstant.player.getID();
const playerName = FBInstant.player.getName();
// Connect to your WebSocket server
const socket = new WebSocket(
`wss://your-game-server.com/room/${contextId}?playerId=${playerId}`
);
socket.onopen = () => {
console.log('Connected to game server');
socket.send(JSON.stringify({
type: 'join',
playerId: playerId,
playerName: playerName,
}));
};
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
handleGameStateUpdate(data);
};
return socket;
}
```
#### Option 2: Use session data for lightweight synchronization
For simpler games (e.g., turn-based or score-comparison games), you can use the SDK's session data and custom update mechanisms to synchronize state without a dedicated server.
```javascript
// Save session-scoped data that other players in the context can read
async function shareGameState(state) {
try {
await FBInstant.player.setDataAsync({
roomGameState: JSON.stringify(state),
});
} catch (error) {
console.error('Failed to save game state:', error);
}
}
```
### Sending updates to Room participants
You can send custom updates to other players in the Room context using `FBInstant.updateAsync()`. This is useful for notifying players about game events, scores, or round results.
```javascript
async function sendRoomUpdate(score) {
try {
await FBInstant.updateAsync({
action: 'CUSTOM',
cta: 'Join the game!',
image: 'data:image/png;base64,...', // Base64-encoded image
text: {
default: `${FBInstant.player.getName()} scored ${score} points!`,
},
template: 'room_score_update',
data: { score: score },
strategy: 'IMMEDIATE',
notification: 'NO_PUSH',
});
} catch (error) {
console.error('Failed to send update:', error);
}
}
```
**Note:** In a Room context, use `strategy: 'IMMEDIATE'` and `notification: 'NO_PUSH'` since players are already present in the Room and do not need push notifications.
### Handling players joining and leaving
Players may join or leave the game session at any time during a Room. Your game should handle these transitions gracefully.
```javascript
// Periodically check for player changes
let knownPlayers = new Map();
async function refreshPlayerList() {
try {
const currentPlayers = await FBInstant.context.getPlayersAsync();
const currentIds = new Set(currentPlayers.map(p => p.getID()));
// Detect new players
currentPlayers.forEach(player => {
if (!knownPlayers.has(player.getID())) {
console.log('New player joined:', player.getName());
onPlayerJoined(player);
}
});
// Detect players who left
knownPlayers.forEach((player, id) => {
if (!currentIds.has(id)) {
console.log('Player left:', player.getName());
onPlayerLeft(player);
}
});
// Update known players
knownPlayers = new Map(currentPlayers.map(p => [p.getID(), p]));
} catch (error) {
console.error('Failed to refresh player list:', error);
}
}
// Call periodically (e.g., every 5 seconds or at round boundaries)
setInterval(refreshPlayerList, 5000);
```
### Complete integration example
Below is a simplified example showing how a game might initialize differently based on whether it is in a Room context.
```javascript
async function startGame() {
// Initialize the SDK
await FBInstant.initializeAsync();
// Report loading progress
FBInstant.setLoadingProgress(50);
// Load game assets
await loadGameAssets();
FBInstant.setLoadingProgress(100);
// Signal that the game is ready
await FBInstant.startGameAsync();
// Determine context and initialize accordingly
const contextType = FBInstant.context.getType();
const contextId = FBInstant.context.getID();
if (contextType === 'ROOM') {
console.log('Rooms Co-Play session detected. Context ID:', contextId);
// Get the list of players in the Room
const players = await FBInstant.context.getPlayersAsync();
console.log(`${players.length} other player(s) in this Room session.`);
// Initialize multiplayer mode
initializeMultiplayerGame(contextId, players);
} else if (contextType === 'THREAD' || contextType === 'GROUP') {
console.log('Playing in a Messenger context.');
initializeSocialGame(contextId);
} else {
console.log('Solo play mode.');
initializeSoloGame();
}
}
startGame();
```
## Best practices for room-based gameplay
### Design for variable player counts
Unlike traditional multiplayer games where you can enforce a fixed player count, Rooms Co-Play sessions can have a variable number of participants (typically 2 to 8, but potentially more). Design your game to work well across a range of player counts.
- Allow the game to start with as few as 1 player and accommodate new players joining mid-session.
- Consider showing a lobby or waiting screen that updates as players join, with a "start" button or auto-start timer.
- If your game requires a minimum number of players, display a friendly message explaining how many more players are needed.
### Keep rounds short
Players in a Room are also having a video conversation. Long, uninterrupted game rounds can make it difficult for players to talk and interact socially. Design short rounds (30 seconds to 2 minutes) with natural break points where players can chat, react, and decide whether to continue.
### Show all players on screen
Room-based play is inherently social. Make sure all participants are visible in the game UI — show player names, avatars (using `player.getPhoto()`), scores, and status. Players should always know who they are playing with and how everyone is doing.
### Handle disconnections gracefully
Players in a Room may experience momentary network issues (especially on mobile with video streaming). If a player temporarily disconnects:
- Do not immediately remove them from the game. Allow a grace period (e.g., 10-15 seconds) for reconnection.
- Show a visual indicator that a player has disconnected rather than silently removing them.
- Allow the game to continue for remaining players if someone does not return.
### Provide audio feedback carefully
Since players are on a video call, any game audio will be picked up by their microphone and transmitted to other participants. Keep this in mind:
- Default game audio to a low volume or muted when in a Room context.
- Use visual feedback (animations, screen effects) as the primary feedback channel rather than relying heavily on sound.
- If you play audio, prefer short, distinct sound effects over continuous background music.
### Make the game easy to understand
Remember that some players in the Room may be encountering your game for the first time because a friend launched it. Keep the rules simple and provide a brief visual explanation at the start of each session. Avoid requiring players to have prior knowledge of game mechanics.
## Limitations and requirements
### Platform availability
- Rooms Co-Play is available on **Facebook Messenger** (iOS and Android). Availability on web and other surfaces may vary.
- Not all devices support Messenger Rooms. On unsupported devices, the games menu will not appear in the Room.
### Player limits
- The maximum number of players in a single Room varies by platform but is typically up to 50 for the Room itself. The number of players who can simultaneously play a game within the Room may be lower depending on device and network constraints.
- Design your game to handle a practical range of 2-8 concurrent players for the best experience.
### No built-in state synchronization
- The platform provides context and player information, but does **not** provide real-time game state synchronization. You must implement your own multiplayer networking using WebSockets, a third-party multiplayer service, or a similar solution for real-time games.
- For simpler interactions (score comparison, turn-based play), you can use the SDK's data storage and update APIs.
### Context switching
- Players cannot switch a Room game context to a different context type (e.g., from `ROOM` to `THREAD`). The context type remains `ROOM` for the duration of the session.
- If a player leaves the Room entirely, they leave the game context as well.
### SDK version
- Rooms Co-Play requires **Instant Games SDK v7.0 or later**. Make sure you are loading a compatible SDK version:
```html
<script src="https://connect.facebook.net/en_US/fbinstant.8.0.js"></script>
```
### Review and approval
- Games that support Rooms Co-Play must still pass the standard Instant Games [quality review](https://developers.facebook.com/documentation/games/launch/reviews/quality-guidelines). There is no separate review process for Rooms Co-Play specifically, but reviewers may test your game in a Room context.
- Ensure that your game works correctly in both Room and non-Room contexts during testing.
## Testing Rooms Co-Play
To test your game in a Rooms Co-Play environment:
1. **Create a test Room:** Open Messenger on your mobile device and start a Room with at least one other person (this can be a test account or a colleague).
2. **Launch your game:** Use the games menu within the Room to find and launch your game. If your game is still in development, make sure the test accounts are listed as testers or administrators in your app's [App Dashboard](https://developers.facebook.com/apps/).
3. **Verify context detection:** Confirm that your game correctly detects the `ROOM` context type and initializes multiplayer mode.
4. **Test player join/leave:** Have participants join and leave the game at various points to ensure your game handles these transitions gracefully.
5. **Test with multiple devices:** Test across iOS and Android devices with different screen sizes and network conditions.
## Next steps
- **[SDK Reference](https://developers.facebook.com/documentation/games/sdk-reference)** — Full API reference for the Instant Games SDK.
- **[Game Performance](https://developers.facebook.com/documentation/games/build/game-performance)** — Optimize your game for fast loading and smooth gameplay.
- **[Building Social Games](https://developers.facebook.com/documentation/games/retain/building-social-games)** — Use Facebook's social features for retention and growth.
- **[Quick Start](https://developers.facebook.com/documentation/games/build/quick-start)** — Build and deploy your first Instant Game.