GS2-Realtime
This feature can be used for low-latency, high-frequency communication to allow game players to play against each other.
GS2 typically charges by the number of API requests, but for this service, once the game server is up and running, a fee is charged for the time the game server is running and for communication capacity. There is no charge per number of communications.
graph TD Match["Lobby established<br/>by GS2-Matchmaking"] --> Want["Request a room with RoomWant"] Want -- Allocated from hot standby --> Warm["Warm Start (1 to 3 seconds)"] Want -- New launch --> Cold["Cold Start (40 to 60 seconds)"] Warm --> Connect["Player connects"] Cold --> Connect Connect --> Play["In-game communication via packet relay"] Play -- No communication for 1 minute or 3 hours elapsed --> Shutdown["Room terminated"]
Server Type
Currently, GS2-Realtime only provides packet relay functionality. This is based on the ability to send a message to a game server, which will then broadcast the message to other players. It also has the ability to specify a player ID and deliver the message only to the specified player.
The SDK does not include features such as RPC or object synchronization, only the ability to send and receive simple binary data. Binary encoding of the payload is the responsibility of the application, so you can adopt any encoding such as Protocol Buffers / FlatBuffers / MessagePack.
Unreal Engine Dedicated Server Hosting
We are looking into the possibility of allowing developers to host a dedicated server built with the Unreal Engine. We have not yet decided when this feature will be available.
If you have a strong need and would like to proceed with development under a paid support contract, we can work out a schedule, so please consult us.
Server Specs
You can set the performance of the server. The performance will make a difference in the price per minute. We have confirmed that the cheapest realtime1.nano can have 8 players send messages to each other 3 times per second.
The Unreal Engine Dedicated Server hosting we are considering will have higher requirements. Unreal Engine Dedicated Server is not recommended for projects where cost efficiency, not development efficiency, is paramount.
The server spec is configured per Namespace, by specifying an identifier such as realtime1.nano in the serverSpec field.
Life Cycle
A game server is not scheduled to start until it receives a startup request.
At this point, GS2 will prepare a hot standby for game servers that receive frequent startup requests. Therefore, allocation can be expected immediately after the startup request is received, but for small-scale games where startup requests do not occur frequently, it takes time from the startup request to the actual allocation.
We refer to the case where the allocation is done from a hot standby as a warm start, and the case where the allocation is done by starting a new server as a cold start. The estimated time required for cold start allocation is about 40 to 60 seconds, while the time required for warm start allocation is assumed to be 1 to 3 seconds.
For titles of a size that do not generate frequent startup requests and where cold start time is unacceptable, Hot Standby can be provided on the assumption that a fixed monthly fee will be charged. We accept contracts for hot standby with a minimum of 5 units.
We cannot guarantee that cold starts will not occur even if you have a hot standby contract or in situations where frequent startup requests are occurring. Cold starts can occur if server startup requests are made faster than hot standby is available or if the game server is being upgraded. Therefore, please design your system with the worst-case scenario of a cold start in mind.
Types of Start
| Type | Time Required | Description |
|---|---|---|
| Warm Start | 1 to 3 seconds | Immediate allocation from hot standby |
| Cold Start | 40 to 60 seconds | Launches a new server process |
Room Termination Conditions
A launched room will be terminated under the following conditions:
- If no one connects within 5 minutes after the room is created
- If all players in the room have been silent for 1 minute
- If the maximum room lifetime of 3 hours is reached
In addition, you can explicitly call RoomShutdown to terminate the room immediately.
Note that the same termination process applies to hot standby rooms as well, but hot standby uptime is not added to your usage charges.
Connecting to a Room
GS2-Realtime uses the following flow for connection.
sequenceDiagram participant Player participant Realtime as GS2-Realtime participant Server as GameServer Player ->> Realtime: Room(roomName).Model() Realtime -->> Player: IpAddress / Port / EncryptionKey Player ->> Server: RelayRealtimeSession.ConnectAsync() Server -->> Player: Connection established Note over Player,Server: After this, communicate directly with the game server over WebSocket
The connection information consists of the following three items:
IpAddress: IP address of the game serverPort: Port number to connect toEncryptionKey: Encryption key for the message payload
When connecting, you pass the access token and the initial profile value of the player.
Profile
Relay servers not only forward received messages to other players, but also allow each player to have profile data.
When a new player connects to the game server, they will receive profile data for all other participating players. Storing basic player information simplifies the process when a new player connects.
When a player updates their profile, the information is sent to other players, so it can be used as a substitute for sending a message. However, it is not optimal in terms of communication efficiency to use high-frequency messaging via profile updates, since the entire payload is sent and received when a profile is updated.
A profile can be encoded as a binary payload in any format. It is suitable for storing snapshots of player character information, equipment, level, in-game currency, etc.
Event Handling
You can set the following event handlers on RelayRealtimeSession.
| Handler | Trigger |
|---|---|
OnJoinPlayer |
When another player joins the room |
OnLeavePlayer |
When another player leaves the room |
OnRelayMessage |
When a relay message is received from another player |
OnUpdateProfile |
When another player updates their profile |
OnError |
When a protocol error occurs |
OnGeneralError |
When a communication error occurs |
OnClose |
When the connection to the game server is closed |
Extended versions including MessageMetadata (such as OnRelayMessageWithMetadata) are also provided for each event, allowing you to also retrieve metadata about the message.
Push Notifications
The main push notifications you can configure and their settings are as follows.
createNotification: Notifies when a room is assigned
Enabling enableTransferMobileNotification also allows mobile push forwarding to offline devices.
By notifying all members gathered by GS2-Matchmaking of the room assignment, you can announce in real time that the match is ready.
Master Data Operation
GS2-Realtime does not require master data. It can be operated solely with namespace settings (server type, server spec, and push notification settings).
Transaction Actions
GS2-Realtime does not provide transaction actions.
Integration with Other Microservices
GS2-Realtime is typically used in combination with the following microservices rather than on its own.
| Service | Purpose |
|---|---|
| GS2-Matchmaking | Match opponents, then call RoomWant once a match is formed |
| GS2-Gateway | Use as the route for the createNotification push notification |
| GS2-Account | Issue player access tokens |
Example Implementation
Obtaining connection information for the game server
Specify the room name to retrieve the connection information.
If the room was prepared via matchmaking through RoomWant, specify its roomName.
var item = await gs2.Realtime.Namespace(
namespaceName: "namespace-0001"
).Room(
roomName: "room-0001"
).ModelAsync();
var ipAddress = item.IpAddress;
var port = item.Port;
var encryptionKey = item.EncryptionKey; const auto Domain = Gs2->Realtime->Namespace(
"namespace-0001" // namespaceName
)->Room(
"room-0001" // roomName
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError()) return false;
const auto Result = Future->GetTask().Result();
const auto IpAddress = Result->GetIpAddress();
const auto Port = Result->GetPort();
const auto EncryptionKey = Result->GetEncryptionKey();Connect to game server
using (
var session = new RelayRealtimeSession(
accessToken, // access token
ipAddress, // game server IP address
port, // game server port
encryptionKey, // encryption key
ByteString.CopyFromUtf8("my profile") // initial profile value
)
)
{
// set event handlers
await session.ConnectAsync();
// scope where session is valid
} // The Realtime SDK for Unreal Engine is currently in preparation.Handling connections from other players
session.OnJoinPlayer += player => {
var connectionId = player.ConnectionId;
var profile = player.Profile;
// Handle initial display for the new participant
}; // The Realtime SDK for Unreal Engine is currently in preparation.Handling disconnections of other players
session.OnLeavePlayer += player => {
// Clean up the display for the leaving player
}; // The Realtime SDK for Unreal Engine is currently in preparation.Handling messages from other players
session.OnRelayMessage += message => {
var sourceConnectionId = message.ConnectionId;
var payload = message.Data;
// Decode and interpret the payload in the application layer
}; // The Realtime SDK for Unreal Engine is currently in preparation.Handling profile updates of other players
session.OnUpdateProfile += player => {
// Reflect profile changes on the screen
}; // The Realtime SDK for Unreal Engine is currently in preparation.Handling disconnects from game server
session.OnClose += () => {
// Retry or transition logic on disconnection
}; // The Realtime SDK for Unreal Engine is currently in preparation.Update profile
await session.UpdateProfileAsync(
ByteString.CopyFromUtf8("my profile2")
); // The Realtime SDK for Unreal Engine is currently in preparation.Send broadcast message
If targetConnectionIds is omitted, the message is delivered to every player in the room except yourself.
await session.SendAsync(
ByteString.CopyFrom(0x00, 0x01, 0x02)
); // The Realtime SDK for Unreal Engine is currently in preparation.Send unicast message
Specify the ConnectionId of the target player in targetConnectionIds.
The ConnectionId can be obtained from events such as OnJoinPlayer.
await session.SendAsync(
ByteString.CopyFrom(0x00, 0x01, 0x02),
new uint[] { targetConnectionId1, targetConnectionId2 }
); // The Realtime SDK for Unreal Engine is currently in preparation.Design Notes
Designing the binary payload
GS2-Realtime simply relays binary data as-is without interpreting its content. Therefore, the following aspects must be designed on the application side:
- A header to identify message types (for example, putting an opcode in the first byte)
- Serialization format (Protocol Buffers / FlatBuffers / MessagePack, etc.)
- Ordering guarantees if needed (assign sequence numbers in the application layer when required)
Cheat Prevention
Since the relay server does not interpret the payload contents, it cannot detect cheating itself. For calculations such as rating, results are determined by majority vote.