Skip to main content

Lifecycle events and actions

Gameplay implementation is just one of the steps in creating a perfect game. There are many other factors that affect the player experience. One of them, staying in close relation to gameplay, is maintaining the match lifetime and the currently playing squad.

If you prefer hands-on experience, check out "Match events" sample project included in Unity SDK package.

Reminder

Make sure Elympics Behaviour component is attached along with your implementation of IServerHandlerGuid, IClientHandlerGuid or IBotHandlerGuid. Otherwise, the callbacks won't be called!

Starting a Match

Starting a match in Elympics is handled by the Rooms system. To start a match, you first need to be in a room. You can create a room using the ElympicsLobbyClient.Instance.RoomsManager.CreateAndJoinRoom method to create a new room and join it.

There are some room requirements to meet before starting a match:

  • Room status must match the queue status, for example: team size, minimum team size filled, etc.
  • All room members must be set to ready.
  • Only the host can start matchmaking.

After matchmaking ends successfully, you need to call IRoom.PlayAvailableMatch to load the gameplay scene. For more information about matchmaking, visit our matchmaking guide.

Joining a Room

In order to join an existing room, you need the Room Guid (for public rooms) or JoinCode (for private rooms). To receive the Guid, you can get a list of all available rooms by using the IRoomsManager.ListAvailableRooms method. A private room's JoinCode has to be shared by another player. After you find the desired room, you can join it by calling ElympicsLobbyClient.Instance.RoomsManager.JoinRoom.

Reconnecting to a Match

Reconnecting to a match in Elympics is also handled by the Rooms system. First, you need to find the room you belong to in order to rejoin the match. You can do this using the RoomsManager and the IRoomsManager.CurrentRoom property. When you have retrieved the desired room and the match is still in progress, you can rejoin the game by calling IRoom.PlayAvailableMatch.

tip

Normally, there is no need to call IRoom.PlayAvailableMatch manually as it is done by Elympics when matchmaking is complete. This behavior is customizable using the "Should Load Gameplay Scene After Matchmaking" checkbox in the ElympicsLobbyClient component of the ElympicsLobby game object.

Elympics Client editor

Joining a match consist of three steps: establish a connection to a game server, then perform user authentication and finally register a player in the match. Completion of each step can be tracked by implementing the following methods from IClientHandlerGuid interface:

  • IClientHandlerGuid.OnConnected(TimeSynchronizationData data)
  • IClientHandlerGuid.OnAuthenticated(string userId)userId becomes null when joining as a spectator
  • IClientHandlerGuid.OnMatchJoined(string matchId)

All of the above methods also have corresponding error handlers:

  • IClientHandlerGuid.OnConnectingFailed()
  • IClientHandlerGuid.OnAuthenticatedFailed(string errorMessage)
  • IClientHandlerGuid.OnMatchJoinedFailed(string errorMessage)

Meanwhile on the server, only one callback is executed:

  • IServerHandlerGuid.OnPlayerConnected(ElympicsPlayer player)

ElympicsPlayer passed here is used to distinguish a player from others in player data array passed as the only parameter of server initialization callback (described below).

Leaving a match

A match can be also left using the IElympics.Disconnect method. If the match isn't ended immediately by the server, players can rejoin it.

Client-only actions

The method above is a client-only action: make sure to call it only if IElympics.IsClient is true.

As matches with players missing have a great chance of becoming unplayable, you may want to close the server after some delay (using the action described in the next section). To make sure the server is notified about such an event, you have to implement IServerHandlerGuid.OnPlayerDisconnected(ElympicsPlayer player).

As before, received in-match player identifier can be used as an index to player data array passed in server initialization callback.

After a client disconnects from a server, it runs its IClientHandlerGuid.OnDisconnectedByClient callback.

Finishing a match

As non-finished games take up resources, ending a match is a crucial step. Game server lifetime is currently limited to 24 hours, so no game runs indefinitely, but surely you don't want a 5-minute match to cost you much more than planned or for your players to wait a whole day until they can play again, because they got stuck in a 24h-long match.

Default server behavior

With ending a game being such an important task, SDK provides a default server handler which closes the match automatically as soon as the first player disconnects. Read more below.

The method you need to call is IElympics.EndGame. Depending on your circumstances, you can pass an optional parameter of type ResultMatchPlayerDatas containing the match results.

The inclusion of ResultMatchPlayerDatas object is essential if you want to take advantage of intelligent matchmaking (using Elo rating or machine learning) or other score-related services provided by Elympics. The data can be also passed to your backend, if configured.

ResultMatchPlayerDatas is a list of ResultMatchPlayerData. Each entry should contain data associated with the corresponding player. As there is no player ID included, you should check InitialMatchPlayerDatasGuid received at the start of the game for the correct order.

ResultMatchPlayerData stores arbitrary byte[] GameEngineData in a format specified by you and float[] MatchmakerData with its structure defined by Elympics. MatchmakerData must contain two elements:

  1. Matchmaker-compatible score. The greater this number is, the higher matchmaker rating. If your game takes a different approach (e.g. you're creating a racing game where time becomes the score), you have to transform your data appropriately.
  2. Game-specific score details. You can put original, unprocessed score here.

You can read more about it in the matchmaking article.

Of course, there are some situations when a match ends with no meaningful results to send to the matchmaker, e.g. not all players joined the game to begin with. In such case you should call EndGame() with no arguments.

When a match ends, the following callbacks are run on clients (in the order listed):

  • IClientHandlerGuid.OnMatchEnded(string matchId),
  • IClientHandlerGuid.OnDisconnectedByServer().
Half-remote

"Half Remote" development mode doesn't currently support the two events listed above. However, the lifetime of a local server can be manipulated freely.

OnDisconnectedByServer

OnDisconnectedByServer is only run at the end of a match. Despite what the name may suggest, there is no possibility of kicking a player from an ongoing game.

DefaultServerHandler

As mentioned earlier, it's really important to end a game correctly. This is why Elympics prefab includes the DefaultServerHandler game object with the DefaultServerHandler component, which closes a match if any connected player leaves. It also calls the IElympics.EndGame method if not all players join a match in the first 30 seconds of the server lifetime.

DefaultServerHandler object inside Elympics prefab

The handler outputs logs to the console when players connect and disconnect and when it decides that the game should be ended. Messages such as "Waiting for game to start" could make you think that games are started using a method analogous to IElympics.EndGame. However, that is not true. A match begins when the server starts up.

Providing a custom implementation

If the behavior described above is not suited for your game, you can disable the built-in implementation of IServerHandlerGuid.

Required replacement

Before you disable DefaultServerHandler, make absolutely sure at least one of your implementations of IServerHandlerGuid calls IElympics.EndGame properly.

DefaultServerHandler component checks Behaviour.isActiveAndEnabled property in every implemented IServerHandlerGuid method, so you can untick DefaultServerHandler component or the whole DefaultServerHandler game object in inspector to prevent it from executing.

Disabling DefaultServerHandler component

Deactivating DefaultServerHandler game object

Alternatively you can just remove DefaultServerHandler component from the DefaultServerHandler object in the instance of the Elympics prefab.

Removing DefaultServerHandler component

Disabling and deactivating Elympics scripts

When it comes to disabling components and deactivating objects, DefaultServerHandler is an exception. All other synchronized behaviors remain unaffected by such settings unless you implement a similar explicit check in your code.

DefaultServerHandler class is a good starting point for implementing a custom server lifetime guard. After copying the code, you can modify it to suit your needs.

Other events

Initialization

When a game instance starts, an initialization callback is run with the game and player data passed as the only parameter. To retrieve the data you can implement the appriopriate methods of IServerHandlerGuid, IClientHandlerGuid and IBotHandlerGuid interfaces.

The data is stored as instances of the InitialMatchPlayerDataGuid class, which consists of the following properties:

  • ElympicsPlayer Player – in-match player identifier
  • string UserId – globally unique player identifier
  • bool IsBot – information if the player is a bot
  • double BotDifficulty – how well a bot should play (if the player is a bot)
  • byte[] GameEngineData – optional game-specific data which you can use to provide initial settings for a match
  • float[] MatchmakerData – optional game and player-related data for matchmaker to learn from (if ML matchmaking is enabled)

For a server, the method is IServerHandlerGuid.OnServerInit(InitialMatchPlayerDatasGuid initialMatchPlayerDatas). initialMatchPlayerDatas is a list of InitialMatchPlayerDataGuid instances, each corresponding to one of the players participating in the match.

For a client, you should implement IClientHandlerGuid.OnStandaloneClientInit(InitialMatchPlayerData data). There is also IClientHandlerGuid.OnClientsOnServerInit(InitialMatchPlayerDatasGuid data) used only in "Local Player and Bots" and "Single Player" development modes. For convenience, it provides a list of all clients run inside the server instance.

For a bot, you can use IBotHandlerGuid.OnBotsOnServerInit(InitialMatchPlayerDatasGuid initialMatchPlayerDatas) as running bots inside the server instance is the default option. As in the case of OnClientsOnServerInit, the method provides a list of data of all bots running in the server.

If you set ElympicsGameConfig.BotsInServer to false, you should use OnStandaloneBotInit(InitialMatchPlayerData initialMatchPlayerData) instead.

The setting is available in Elympics Game Config:

"Bots inside server" setting in Elympics Game Config

Providing InitialMatchPlayerDatasGuid

There are two points at which you can input GameEngineData and MatchmakerData for your game to use during the initialization process.

The first is when you call IRoomsManager.StartQuickMatch. This method accepts several optional parameters, including float[]? matchmakerData and byte[]? gameEngineData. Check out the matchmaking article for more details.

Initial match data in development modes

Development modes aren't started using the StartQuickMatch method. You need to place the game engine and matchmaker data in Test players section of your Elympics Game Config instead.

Test players section

The second approach requires using your own backend. The list of required endpoints can be found in External Game Backend integration chapter, along with the instructions on how to configure the backend address to be used by your game.

Clock synchronization

The IClientHandlerGuid.OnSynchronized(TimeSynchronizationData data) method is called every time a client synchronizes its clock with the server (using NTP protocol).

An implementation of this method can be used to track the condition of network connection using information from a TimeSynchronizationData object passed as the only parameter. For example the RoundTripDelay property can be displayed as "ping" in an in-game UI. When working with RoundTripDelay, keep in mind that this is raw data from a single measurement. OnSynchronized is called frequently and the value of RoundTripDelay can change rapidly.

Displaying ping

Consider using a moving average or a similar technique to "smooth" the data before displaying RoundTripDelay to a player.