Game Instance Tasks #

Game Instance features are built and customized using a combination of calls and plugin methods. This page describes common game instance operations, along with descriptions of SDK actions and related plugin methods.

Game instance initialization

Player management

End of game

For a full list of all available Game Instance SDK and plugin functions, see Game Instance Reference.

Initialize Game Instance SDK (Required) #

Before you can use the Game Instance API, you must initialize the Game Instance SDK using the Initialize method. Calling Initialize will sync the game server cache with the game instance data from the Pragma Engine backend.

Initialize() can only be called after login. Upon logout, the service is un-initialized. You must call initialize() on the service when you log back in.
Player->GameInstanceApi().Initialize(
  const FOnCompleteDelegate& OnComplete
);
Player.GameInstanceApi.Initialize(
  CompleteDelegate onComplete
);

After you receive a successful response, you can begin using the Game Instance API.

While the Pragma SDK constantly attempts to stay in sync with the Pragma Engine backend, there may be instances where the two components become out of sync due to connection issues. To forcibly synchronize the player client’s game instance data with the platform’s game instance data, call the Game Instance API ForceSync function.

Find host for a game instance #

Find a game server to host the game instance

When the Matchmaking service creates a new game instance and sends the information to the Game Instance service, game instance allocation can begin. The Game Instance Host Plugin’s findHostForGameInstance aids in allocating a game server for a specific game instance:

fun findHostForGameInstance(
  gameInstance: GameInstance 
  clientTokenFunction: () -> PartnerClientTokens
): ExtHostRequest?

Implement findHostForGameInstance in the following ways.

If using a third-party game server fleet manager:

  • Integrate with your game server fleet manager to allocate a game server for this game instance by providing the game server with the Pragma backend address and the game instance ID the game server should be starting.
  • Provide connection tokens to the game server using the clientTokenFunction parameter, as shown in the following example:
suspend fun findHostForGameInstance(gameInstance: GameInstance, clientTokenFunction: () -> PartnerClientTokens) {
  val token = clientTokenFunction()
  val dispatchRequest = mapOf(
    META to mapOf(
      ...
      PARTNER_GAME_AUTH_TOKEN to token.gameToken,
      PARTNER_SOCIAL_AUTH_TOKEN to token.socialToken,
    )
  )
}
  • Return null
Each game server requires a set of partner tokens, regardless of how many game instances that game server can run at once.

If using the Pragma Fleet service:

  • Prepare and return any custom data (ExtHostRequest) needed to build server pool selection logic.
  • Use the FleetPlugin.add method to define how game servers spin up for their respective server pool. The FleetPlugin.add method accepts GameServerAllocation objects, which contain server IDs and partner tokens. See Fleet Service Tasks for more information.

Related events:

Related errors:

Send custom game data to the game server #

Send game and player data to the game server

Send custom data to game server

Declare custom data #

When a game server is allocated a game, the Game Instance Plugin’s buildExtGameStart plugin method is invoked once. This method builds the ExtGameStart payload, which declares custom data to start the game instance.

suspend fun buildExtGameStart(
    gameInstance: GameInstance.GameInstance
): ExtGameStart

The Game Instance Plugin’s buildExtGameServerPlayer plugin method is also invoked for each player in the game. This method builds the ExtGameServerPlayer payload, which declares custom data to send to the game server for a player.

suspend fun buildExtGameServerPlayer(
    gameInstance: GameInstance.GameInstance, 
    player: GameInstance.GamePlayer
): ExtGameServerPlayer

Update custom game data #

You can update this data at any time using the UpdateGameInstance SDK method. Use the ExtUpdateGameInstanceRequest payload to describe how the game instance data should be updated.

Update game instance

Server->MatchApi()->UpdateGameInstance(
  const FString& GameInstanceId,
  const FPragma_GameInstance_ExtUpdateGameInstanceRequest& RequestExt,
  const UPragmaGameInstancePartnerServiceRaw::FUpdateGameInstanceV1Delegate& Delegate
);
Server.MatchApi.UpdateGameInstance(
  PragmaId gameInstanceId
  ExtUpdateGameInstanceRequest requestExt,
  Action<Result<UpdateGameInstanceV1Response>> callback
);
{
  "requestId": 17,
  "type": "gameInstanceRpc.UpdateGameInstanceV1Request",
  "payload": {
    "game_instance_id": "1",
    "request_ext":{}
  }
}

When called, the UpdateGameInstance SDK method will trigger the Game Instance plugin method updateGameInstance. This plugin function provides full access to the game instance data, allowing you to update existing game data with information contained in the ExtUpdateGameInstanceRequest.

suspend fun updateGameInstance(
    gameInstance: GameInstance.GameInstance,
    requestExt: ExtUpdateGameInstanceRequest
)

For example, you may have a currently running game instance whose matchmaking needs change depending on the game’s state. If a game disproportionately favors one team, you might want to adjust what skill level you are looking for in a new player. You can specify this information in the ExtUpdateGameInstanceRequest ext.

If the game instance being updated is currently in matchmaking, all of the matchmaking ext payloads for this game instance will be recalculated and sent to matchmaking to ensure the matchmaking representation of the game instance is up to date. See Enter matchmaking to connect more players for more information about which plugins are invoked during this operation.

Related events:

Related errors:

Connect players to a game instance #

Verify and add players to a game instance.

Verify player

Players and parties are added to game instances via the NewGameInstance object (for newly created game instances) or the GameInstanceUpdate object (for existing games accepting new players/parties) that is sent to the Game Instance service.

Send connection details #

After server allocation, the game instance host calls MatchApi.ConnectPlayers to indicate that it’s ready for players to join the game instance. Players receive a OnHostConnectionDetailsReceived notification, which includes host connection details such as host name, port, game instance ID, the ExtPlayerConnectionDetails payload (which can be used to define custom game server host information), and a unique connection token.

Server->MatchApi()->ConnectPlayers(
  const FString& GameInstanceId,
  const TArray<FPragma_GameInstance_PlayerConnectionDetails>& PlayerConnectionDetails,
  const FString& Hostname,
  const int Port,
  UPragmaGameInstancePartnerServiceRaw::FConnectPlayersV1Delegate Delegate
);
Server.MatchApi.ConnectPlayers(
  PragmaId gameInstanceId,
  IEnumerable<PlayerConnectionDetails> playerConnectionDetails, 
  string hostname, 
  int port,
  Action<Result<ConnectPlayersV1Response>> callback
);

Verify players #

Pragma Engine can use the player connection tokens to verify the correct players join a game instance. The player verification process is optional, but recommended for competitive games.

The player client needs to provide the connection token to the game server upon joining the game instance. The game server then sends the connection token to the engine via MatchApi.VerifyPlayer so the engine can validate the connection token. If the engine determines the connection token is valid, players can join the game instance.

Server->MatchApi()->VerifyPlayer(
  const FString& GameInstanceId,
	const FString& PlayerId,
	const FString& ConnectionToken,
	UPragmaGameInstancePartnerServiceRaw::FVerifyPlayerPartnerV1Delegate Delegate
);
Server.MatchApi.VerifyPlayer(
  PragmaId gameInstanceId, 
  PragmaId playerId, 
  string connectionToken,
  Action<Result<VerifyPlayerPartnerV1Response>> callback
);

A player who disconnects and reconnects to the same game instance will receive the same connection token on the OnGameInstanceReconnect notification.

See the Matchmaking Tasks topic for more information on adding parties to game instances.

Send custom game data to players #

Send custom data to players

When a player is added to a game, the OnAddedToGame event triggers with the ExtAddedToGame payload. The buildExtAddedToGame function allows for customization of ExtAddedToGame data to send to the player when they are added to a new game. This data will be sent to the players immediately, even if a game server is still preparing to host the game instance.

suspend fun buildExtAddedToGame(
    gameInstance: GameInstance.GameInstance,
    player: GameInstance.GamePlayer
): ExtAddedToGame

Related events:

Related errors:

Add more players #

Connect more players to your game instance

Add more players

Game instances can enter matchmaking to accept more players. When a game instance enters matchmaking, the Game Instance Matchmaking Plugin builds customized data about the game instance (ExtMatchmakingGameInstance), the parties within it (ExtMatchmakingGameParty), and the players within it (ExtMatchmakingGamePlayer).

suspend fun buildExtMatchmakingGameInstance(
    gameInstance: GameInstance.GameInstance
): ExtMatchmakingGameInstance
  
suspend fun buildExtMatchmakingGameParty(
    gameInstance: GameInstance.GameInstance,
    party: GameInstance.GameParty
): ExtMatchmakingGameParty

suspend fun buildExtMatchmakingGamePlayer(
    gameInstance: GameInstance.GameInstance,
    party: GameInstance.GameParty,
    player: GameInstance.GamePlayer
): ExtMatchmakingGamePlayer

The data in these ext payloads will be made available to the Matchmaking Plugin’s matchPartiesWithGame function via the Matchmaking.GameInstance object when comparing game instances. (See Add parties and players to active game instances).

If, after creating a Game Instance Update object, you want the Matchmaking Game Instance to leave matchmaking, use GameInstanceUpdate.stopMatchmaking. See Leave matchmaking as a game instance for specifics.

Related events

Related errors:

Reconnect players #

Reconnect disconnected players to the same game instance

Pragma allows players to reconnect to their game instance after disconnecting from the engine. This feature can be configured via the GameInstanceServiceConfig.reconnect config value:

valuedescription
OFF(Default) When the player disconnects from Pragma Engine, the player is removed from their game instance.
OPTIONALWhen the player disconnects from Pragma Engine, they remain in the game instance. When the player reconnects to the engine, they have the option to call the DeclineReconnect() SDK method, which will remove them from the game instance.
REQUIREDWhen the player disconnects from Pragma Engine, they remain in the game instance. When the player reconnects to the engine, they don’t have the option of calling the DeclineReconnect() SDK method.

To check if a reconnected player is still in a game instance, use the GameInstanceApi.GetGameInstanceCache() SDK method. This method will also return host connection details so the player client can connect to the appropriate game server.

If the player is reconnecting to the engine due to logging out, call GetGameInstanceCache() immediately after GameInstanceApi.Initialize() to check if the player is still in a game instance.

Related events

Related errors:

Remove players #

Remove one or more players from the current game instance

Remove players from game

The game server can call MatchApi.removePlayers to remove one or more players from an active game instance. Game results and metrics can be stored in the ExtRemovePlayersRequest payload (for game-specific data) and the ExtRemovePlayer payload in the list of players to remove (for player-specific data).

Server->MatchApi()->RemovePlayers(
  const FString& GameInstanceId,
  const TArray<FPragma_GameInstance_PlayerToRemove>& Players,
  const FPragma_GameInstance_ExtRemovePlayersRequest& Ext,
  UPragmaGameInstancePartnerServiceRaw::FRemovePlayersV1Delegate Delegate
)
Server.MatchApi.RemovePlayers(
  PragmaId gameInstanceId, 
  IEnumerable<PlayerToRemove> players,
  ExtRemovePlayersRequest ext, 
  Action<Result<RemovePlayersV1Response>> callback
)
{
  "requestId": 19,
  "type": "gameInstanceRpc.RemovePlayersV1Request",
  "payload": {
    "game_instance_id": "1",
    "players": {},
    "ext":{}
  }
}

After a player has been removed from the party, the Game Instance Plugin onRemovePlayers is called. This method is used to prepare any custom data (ExtRemovedFromGame) to send to the removed players.

suspend fun onRemovePlayers(
    gameInstance: GameInstance.GameInstance,
    playersToRemove: List<PlayerToRemove>,
    requestExt: ExtRemovePlayersRequest
): Map<PlayerId, ExtRemovedFromGame>

Removed players will receive the onRemovedFromGame event with the ExtRemovedFromGame payload.

Upon removal, the removed players will appear in the removedPlayers list on the GameInstance.GameInstance. If the same players are added back into the game instance via matchmaking, they will be removed from the removedPlayers list and appear within the players list as a part of the new party that they joined the game with.

RemovePlayers also invokes the Party Plugin’s returnFromGameInstance method and provides a list of the specific players being removed from the game. See Party Service Tasks: Return from a game instance for more information.

Players removed from the game instance before the game ends can still be included in end game processes and receive end game data.

Related events:

Related errors:

End a game instance #

End a game instance for all players

End game

EndGame must be invoked to end the game instance, even if all players have left the game instance.

The game server is required to call MatchApi.EndGame to end the game instance and perform end game processes, even if no players remain in the game instance.

Server->MatchApi()->EndGame(
  const FString& GameInstanceId,
  const TArray<FPragma_GameInstance_PlayerGameResult>& PlayerGameResults,
  const FPragma_GameInstance_ExtEndGameRequest& Ext,
  UPragmaGameInstancePartnerServiceRaw::FEndGameV1Delegate Delegate
)
Server.MatchApi.EndGame(
  PragmaId gameInstanceId, 
  IEnumerable<PlayerGameResult> playerGameResults,
  ExtEndGameRequest ext, 
  Action<Result<EndGameV1Response>> callback
)
{
  "requestId": 20,
  "type": "gameInstanceRpc.EndGameV1Request",
  "payload": {
    "game_instance_id": "1",
    "player_game_results": {},
    "ext":{}
  }
}

After the game instance has ended, the Game Instance Plugin onEndGame method is invoked to create a new ExtGameEnded payload per player. This payload can store game results, metrics, grants, and other end game data.

suspend fun onEndGame(
    gameInstance: GameInstance.GameInstance,
    playerGameResults: List<PlayerGameResult>,
    requestExt: ExtEndGameRequest
): Map<PlayerId, ExtGameEnded>

Players removed from the game instance before the game ends can be included in end game processes and receive end game data. This is useful if you have a game that issues additional rewards to players at the end of the game, whether or not they are still active.

Players will receive the onGameEnded event with the ExtGameEnded payload that relates to them. This notification indicates that the end of game information has been successfully processed, and the game instance has ended.

EndGame also invokes the Party Plugin’s returnFromGameInstance method and provides a list of players currently in the game instance. This list does not include players previously removed from the game instance. See Party Service Tasks: Return from a game instance for more information.

Related events:

Related errors:

Handle game end failures #

Pragma Engine provides two features to account for situations where the end game request never arrives: Keep Alive Heartbeats and Absolute Timeouts. A game end payload can fail to arrive due to game server crashes, game code bugs, network issues, or malicious actors. These features help release players from a game instance and allow them to reenter the game loop to start a new game instance.

In these failure situations, the player receives an OnGameInstanceTerminated event, including a reason for shutdown.

When the game is forced to shut down, no end game data is processed.

Related events

Keep alive heartbeats #

The Keep Alive Heartbeats feature requires game servers to send occasional heartbeats after starting a game instance. This allows Pragma Engine to confirm that the game instance and game server are still operational.

When enabled, Pragma Engine expects a MatchKeepAliveV1 request based on the configured amount of time (keepAliveIntervalMillis). If the engine doesn’t receive the request after a consecutive set of the configured amount of missed values (keepAliveMissesLimit), it ends the game instance and returns players to their party, calling the Party Plugin returnFromGameInstance method.

Game servers using the Pragma Engine-provided Unreal and Unity SDKs automatically send heartbeats to Pragma Engine on a successful response of the ConnectPlayers method when this feature is enabled. It does this by starting a background process that makes the necessary MatchKeepAliveV1 requests every keepAliveIntervalMillis while the match is progress.

The configuration for this feature can be found in GameInstanceServiceConfig. This feature is enabled by default, with a 30000 milliseconds (30 seconds) value for keepAliveIntervalMillis in production environments, and a keepAliveMissesLimit value of 3.

A separate keepAliveIntervalMillis configuration for development in dev-defaults.yml is set to 5000 milliseconds (5 seconds). To modify these values, edit the local-dev.yml file.

To disable this feature, set the GameInstanceServiceConfig.enableKeepAlive configuration property to false.

As a best practice, we recommend against turning off the Keep Alive Heartbeats feature, as it’s critical for game flow health.

Absolute timeouts #

The Absolute Timeouts feature makes Pragma Engine end a game instance after a specified period of time elapses.

To enable this feature, set the GameInstanceServiceConfig.enableAbsoluteTimeout configuration property to true and provide a value for GameInstanceServiceConfig.absoluteTimeoutMillis.

Once enabled, Pragma Engine starts a background task that runs after a configured amount of time (absoluteTimeoutMillis) passes. If a game instance is still in progress when the background task runs, the engine ends the game instance and returns players to their party, calling the Party Plugin returnFromGameInstance method.

This process releases the game instance from the Game Instance Service. The game server itself may still need to end or cleanup the game, and/or shutdown.

Related events