Architecture details
Matchmaking
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
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
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.