Skip to main content

Architecture details

Matchmaking

Part1

Matchmaker

All begins within Matchmaker. In this example we are going to use 2-player game.

After both players join matchmaker queue, Matchmaker matches them. Depending on chosen options, matching can be done:

  • taking players from social queues or private queues (joined using invite links),
  • in the debug instant mode,
  • with bots present,
  • employing machine learning or ELO ranking system.

Then Matchmaker sends information about the chosen game and matched players to MatchCreationService.

Creating match

MatchCreationService is a microservice with responsibility of creating matches. Match creation consists of 3 major steps.

First step takes place only if developer configured External game backend. The backend is required to approve matches so a request with matched players data and game version details is sent to it. When producing a response, External game backend can add or modify player data to be used in the match.

Second step is to try to allocate a game server for hosting the match. Match parameters are sent to Fleet and program awaits a response with successful allocation. If there is no game server available, timeout occurs and proper information is passed to be saved in database.

Third step is to save match parameters and result of allocation to Matches database. From now on players can retrieve this information and periodically check if GameServer is ready to accept players and what is the status of game engine.

Fleet and Game Server allocation

Fleet serves as a pool of GameServers, allocating them on demand. You can find basic types of fleets in elympics web panel:

  • Starter,
  • Basic,
  • Premium,
  • Ultimate.

Fleet handles requests for GameServer allocation. If there's an unoccupied one available, it is immediately returned. Otherwise the service tries to autoscale and create new GameServers. When there are no free resources to autoscale, then match creation fails and proper information is saved to database for players to retrieve.

Game Server

Part2

tip

To enter Finish Match stage, server has to call EndGame() method.

Initialization

The initialization of GameServer starts with match information called MatchInitData passed from Fleet to specific GameServer. Then, based on gameId and gameVersion, proper game engine is downloaded from Game Engine Storage and loaded by GameServer. The main part of a game engine is C# interface IGameEngine (currently in 3 versions V1.1, V1.2 and V1.3 with incrementally added features). It consists of methods:

  • Init,
  • Tick,
  • OnPlayerConnected,
  • OnInGameDataFromPlayerReliableReceived,
  • InGameDataForPlayerOnReliableChannelGenerated etc.

Init method runs at the beginning and then other methods are called when associated events occur.
Unity SDK is tightly coupled with these methods and Elympics starts Unity process with its own initalization and coordinates all communication.

After initialization process finishes, GameServer saves all details into Matches Database.

Running a match

Part3

If you want to read more about events called in client and server instances at the start and in the middle of a match, visit the lifecycle article.

Match is the heart of whole Elympics – the place where gameplay is happening.

Players connect to a fully loaded and started GameEngine using provided C# GameServerClient or your own implementation.

Connection

First step is to connect at the low sockets level. Elympics are supporting 2 modes of connection:

  • TCP/UDP - used in Android, iOS, Windows, Linux or Unity Editor,
  • WebRTC - used in WebGL builds or Unity Editor.

These are supported by GameServerClient with methods ConnectTcpUdpAsync and ConnectWebAsync.

Authentication

Then client has to authenticate on GameServer with provided match secret received from Lobby. Otherwise it will be disconnected. There is also possibility to authenticate as a Spectator but this option is not currently supported in Unity SDK (you can implement it using pure IGameEngine).

These are supported by GameServerClient with methods AuthenticateMatchUserSecretAsync and AuthenticateAsSpectatorAsync. Right after authentication client can explicitly join match using JoinMatchAsync method.

Synchronization

The last thing to setup to correctly play a game is to synchronize clock with GameServer using Network Time Protocol. This is split to 2 stages:

  • initial synchronization - to test if it's working,
  • continuous synchronization - to run asynchronously through the game.

It is required to measure latency and clock offset between each client and the server.

Exchanging inputs and snapshots

Finally client can send inputs and receive snapshots from server until match is finished.

Results

When a match is finished, GameServer is informed about it. If game ended gracefully, the information may include List<ResultMatchPlayerData>. The results are sent to MatchesDatabase, saved and then passed to:

  • External Game Backend (if configured),
  • Matchmaker,
  • Room Service (in development),
  • Leaderboard Service (in development),
  • etc.