専用サーバーでのマッチメイキングに SDK を使用する - 専用サーバーでのクイックマッチ - (Unity モジュール)
Unwrap the wrapper
After setting up a Match Pool, you will call the AccelByte Gaming Services (AGS) Game SDK for dedicated server (DS) matchmaking. This is done in the MatchmakingSessionDSWrapper
class in the StartDSMatchmaking
function to initiate the matchmaking process using a dedicated server, since you will use the Match Pool name you set up previously with the dedicated server in its Session Template.
Implement dedicated server matchmaking
You will continue the dedicated server matchmaking implementation in the MatchmakingSessionDSWrapper_Starter.cs
file.
You need to create a matchmaking ticket based on the Match Pool name.
MatchmakingSessionDSWrapper_Starter.cs
is a subclass ofMatchmakingSessionWrapper
, so you don't an instance to get the game client event. Since you will use dedicated server as the gameplay sever type, the game client needs the game server. The server coexists in this project, and theUNITY_SERVER
defined symbols are defined when the server build settings are enabled in the Unity Editor Build Settings.private void Start()
{
#if UNITY_SERVER
GameManager.Instance.OnRejectBackfill += () => { isGameStarted = true; };
GameManager.Instance.OnGameStateIsNone += () => { isGameStarted = false; };
#endif
}ImportantAnonymous functions that listen to
GameManager.Instance.OnRejectBackfill
event to change theisGameStarted
flag are needed because the server should reject any backfill proposal when the game starts.When matchmaking starts, you will call the
StartMatchmaking
function inMatchmakingSessionDSWrapper
. You also need to check whether the game is set up for a local dedicated server or a cloud dedicated server. ModifyMatchmakingSessionDSWrapper_Starter.StartDSMatchmaking
as follows:protected internal void StartDSMatchmaking(string matchPool)
{
ConnectionHandler.Initialization();
StartMatchmaking(matchPool, ConnectionHandler.IsUsingLocalDS());
}You will handle the ticket creation status in the
OnStartMatchmakingComplete
function inMatchmakingSessionDSWrapper_Starter
. Once matchmaking ticket creation succeeds, you will fireOnStartMatchmakingSucceedEvent
, the event that will be listened for by the UI. ModifyOnStartMatchmakingComplete
inMatchmakingSessionDSWrapper_Starter
as follows:private void OnStartMatchmakingComplete(Result<MatchmakingV2CreateTicketResponse> result)
{
if (!result.IsError)
{
matchTicket = result.Value.matchTicketId;
OnStartMatchmakingSucceedEvent?.Invoke(matchTicket);
}
else
{
OnStartMatchmakingFailed?.Invoke();
}
}Since you already listen for the on match found event, when the match is found you will join the found match session. Once a match is found, you still need to listen to the on join session complete event and then try to join the game session of the match. Modify the
OnJoiningMatch
inMatchmakingSessionDSWrapper_Starter
as follows:private void OnJoiningMatch(string sessionId)
{
isOnJoinSession = true;
JoinSession(sessionId);
}MatchmakingSessionWrapper
will listen to the on joined match session event, and also to the dedicated server available (ready to receive a client connection) event. Once a dedicated server is available, you will fire an event that will be listened to by the UI to start the connection to the dedicated server. ModifyOnSessionDSUpdate
inMatchmakingSessionDSWrapper_Starter
as follows:private void OnSessionDSUpdate(Result<SessionV2DsStatusUpdatedNotification> result)
{
if (!result.IsError)
{
var session = result.Value.session;
var dsInfo = session.dsInformation;
switch (dsInfo.status)
{
case SessionV2DsStatus.AVAILABLE:
if (!isFired)
{
isFired = true;
OnDSAvailableEvent?.Invoke(session);
}
break;
case SessionV2DsStatus.FAILED_TO_REQUEST:
BytewarsLogger.LogWarning($"{dsInfo.status}");
OnDSFailedRequestEvent?.Invoke();
break;
default:
BytewarsLogger.Log($"{dsInfo.status}");
break;
}
}
else
{
Debug.Log($"{result.Error.Message}");
}
}
Handle Backfill
Your game server might not always have the maximum number of players. To fill your game server with new players, you can implement backfill during matchmaking.
Define a variable called
serverDSHub
that will store any functionalities related to DS Hub notifications. Then, you need to definematchmakingV2Server
that will store functionality about accepting and rejecting backfill proposals. In theAwake()
function, add the following code:private void Awake()
{
base.Awake();
#if UNITY_SERVER
matchmakingV2Server = MultiRegistry.GetServerApiClient().GetMatchmakingV2();
serverDSHub = MultiRegistry.GetServerApiClient().GetDsHub();
#endif
}From the game server side, it is required to connect to the DS Hub to subscribe to any notifications from AccelByte Gaming Services (AGS). The connection to DS Hub has been done in
ArmadaV3Wrapper.cs
. The instance of the class is instantiated in theMultiplayerDSEssentialsWrapper
and referenced in theStart
function ofMatchmakingSessionDSWrapper_Starter
. You subscribed to notifications from AGS in theStart()
function previously. To subscribe to additional notifications, you will add some additional code in theMatchmakingSessionDSWrapper_Starter
class. Subscribe to two events:MatchmakingSessionDSWrapper_Starter.MatchMakingServerClaim()
will listen if a server is claimed and assigned to a session.MatchmakingSessionDSWrapper_Starter.BackFillProposal()
which listen to backfill proposals.
Modify
MatchmakingSessionDSWrapper_Starter.MatchMakingServerClaim()
as follows:public void MatchMakingServerClaim()
{
serverDSHub.MatchmakingV2ServerClaimed += result =>
{
if (!result.IsError)
{
var serverSession = result.Value.sessionId;
GameData.ServerSessionID = serverSession;
BytewarsLogger.Log($"Server Claimed and Assigned to sessionId = {serverSession}");
}
else
{
BytewarsLogger.LogWarning($"Failed to get server claim event from server");
}
};
}Modify
MatchmakingSessionDSWrapper_Starter.BackFillProposal()
as follows:private void BackFillProposal()
{
serverDSHub.MatchmakingV2BackfillProposalReceived += result =>
{
if (!result.IsError)
{
BytewarsLogger.Log($"BackFillProposal");
if (!isGameStarted)
{
OnBackfillProposalReceived(result.Value, isGameStarted );
BytewarsLogger.Log($"Start back-filling process {result.Value.matchSessionId}");
}
else
{
OnBackfillProposalRejected(result.Value);
}
}
else
{
BytewarsLogger.LogWarning($"BackFillProposal {result.Error.Message}");
}
};
}Create a function to accept and reject the backfill proposal. Open the
MatchmakingSessionDSWrapper_Starter
and modifyOnBackfillProposalReceived
as follows to accept backfill:private void OnBackfillProposalReceived(MatchmakingV2BackfillProposalNotification proposal, bool isStopBackfilling)
{
matchmakingV2Server.AcceptBackfillProposal(proposal, isStopBackfilling, result =>
{
if (!result.IsError)
{
BytewarsLogger.Log($"Back-filling accepted {!isStopBackfilling}");
}
});
}To reject the backfill proposal, modify
OnBackfillProposalRejected
as follows:private void OnBackfillProposalRejected(MatchmakingV2BackfillProposalNotification proposal)
{
matchmakingV2Server.RejectBackfillProposal(proposal, true, result =>
{
if (!result.IsError)
{
BytewarsLogger.Log($"Back-filling rejected - Game already started");
}
});
}Compile to make sure there are no errors.
Resources
- The file used in this tutorial section is available in the ByteWars GitHub repository.