Realtime: Synchronize two players
Connect two game windows to the same room. Move a character with WASD, then press Space to briefly enlarge that character on both screens.
Use the GS2 tutorial project and Unity project from the basics. On this page, create a new RealtimePractice scene and connect through the SDK.
1. Create a Realtime namespace
In the management console, open the Tokyo region of your tutorial project.
- Open Realtime → Namespace list → Create namespace.
- Enter the following values and create it.
| Field | Value |
|---|---|
| Name | adventure-sync |
| Server type | Object synchronization (sync) |
| Server specification | realtime1.nano |
2. Create a scene with login
- In Unity, create an empty scene with File → New Scene and save it as
RealtimePractice. - Save AdventureLogin.cs in
Assets. If you already have the file, use that copy. - Create an empty
Loginobject and addAdventureLogin. - From Deploy → Default → Output list in the management console, copy
ApplicationClientIdandApplicationClientSecretinto Client Id / Client Secret. - Set Account Namespace to
Accountif you created accounts with Studio, oradventure-accountfor the SDK course. Set Account Slot torealtime-a. - Set Edit → Project Settings → Player → Other Settings → Active Input Handling to Both. Restart Unity if prompted.
- In the same Player settings, enable Resolution and Presentation → Run In Background. This keeps synchronization running in the built app while you use another window.
3. Create the synchronized character
Save these two files in Assets.
- AdventureRoomPlayer.cs: movement and Space key input.
- AdventureRoomEmote.cs: an action performed on everyone’s screen.
The movement code changes the Transform. NetworkTransform, added in the next steps, sends the position to the other screens.
var move = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
transform.position += move.normalized * (3f * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.Space))
GetComponent<NetworkEntity>().Rpc(nameof(AdventureRoomEmote.Wave), RpcTarget.All);An RPC runs a specified action on other participants’ screens too. Here, Wave, marked with [NetworkRpc], enlarges the character for 0.3 seconds.
[NetworkRpc]
public IEnumerator Wave(NetworkRpcInfo info)
{
transform.localScale = Vector3.one * 1.5f;
yield return new WaitForSeconds(0.3f);
transform.localScale = Vector3.one;
}Each character has a player who owns its controls. Register the movement script under Controlled Behaviours so your input does not move the other player’s character. Scripts in this list run only on the owner’s screen.
- Create GameObject → 3D Object → Capsule and name it
NetworkPlayer. - Add the following components.
| Component | Settings |
|---|---|
| Network Entity | Leave Schema empty. Add this object’s AdventureRoomPlayer to Controlled Behaviours |
| Network Transform | Position Axes: All; Rotation Axes: None |
| Adventure Room Player | Keep the defaults |
| Adventure Room Emote | Keep the defaults |
- Drag
NetworkPlayerinto the Project window to create a Prefab. Delete the Capsule remaining in the Hierarchy.
4. Create the connection object
- In the Project window, choose Create → GS2 → Realtime → Prefab Catalog and create
PracticeCatalog. - Add one entry to Prefabs, with Id
1and PrefabNetworkPlayer. - Save AdventureRoom.cs in
Assets. - Create an empty
Roomobject and addAdventureRoom.NetworkWorldandNetworkSessionare added automatically. - Assign
PracticeCatalogto Network World → Prefab Catalog, and theLoginobject’sAdventureLoginto Adventure Room → Login. - Create the ground with GameObject → 3D Object → Plane.
- Create GameObject → Camera, name it
Main Camera, and set its Tag toMainCamera. Set position to(0, 12, -10)and rotation to(50, 0, 0). - Create GameObject → Light → Directional Light and set its rotation to
(50, -30, 0).
The connection code looks up the room’s IP address, port, and encryption key by name, then passes them along with the logged-in player’s access token.
session.Connect(login.Session.AccessToken.Token,
get.IpAddress, get.Port, get.EncryptionKey);
await UniTask.WaitUntil(
() => session.State == NetworkSessionState.Ready || session.State == NetworkSessionState.Disconnected,
cancellationToken: this.GetCancellationTokenOnDestroy());Once connected, Ready is called and spawns the character with Prefab ID 1.
world.Instantiate(1,
new Vector3(Random.Range(-3f, 3f), 1, Random.Range(-3f, 3f)),
Quaternion.identity);5. Move characters in two windows
- Save the scene and create a desktop build under File → Build Profiles. Add
RealtimePracticeto the scene list, uncheck the other scenes, and enable onlyRealtimePracticefor this build. - Start the built app, set the login screen’s account slot to
realtime-a, and click Log in. Enter Play Mode in the Unity Editor too, set its slot torealtime-b, and log in. - In the management console, open Room list → Create room for
adventure-sync. Create a room namedpractice. Leave the notification user ID list empty. - Refresh the list. When
practiceshows an IP address and port, click Connect to this room with room namepracticein both the app and Unity Editor. - Once both windows show two characters, click one game window and press WASD. The same character moves in both windows.
- Press Space and check that the character briefly grows on both screens.
6. Transfer control to the other player
- Copy My connection ID from B’s screen into A’s Connection ID to transfer control to field.
- For an object owned by A, click Transfer control of this object. Note its object number.
- WASD on A no longer moves that character. On B, it moves both the original character and the transferred one.
- Enter A’s connection ID on B and return control of the noted object to A. Each player can control one character again.
Transfer control with entity.TransferOwnership(otherConnectionId). When ownership changes, the movement script in Controlled Behaviours becomes enabled on the new owner’s screen.
7. Disconnect and reconnect
Click Disconnect on A. A’s character disappears from B’s screen. Reconnect A to the same room: a new character appears, while B’s character is shown at its current position.
When finished, disconnect both windows. In the management console, delete the practice room from adventure-sync’s room list.
To manage enemy HP and game results on the server, see the GSL enemy tutorial (new tab), from defining rules to trying them in Unity.