C++ を使用した統合
Use the Matchmaker Subsystems and API to add matchmaking functionality to your Unreal Engine game in C++.
読み終わるまでの所要時間 5 分最終更新 4日前
以下のセクションでは、Unreal Engine のサブシステムを使用して Matchmaker SDK を統合する方法を示します。 Unity Gaming Services SDK では、次の 2 つの Matchmaker インターフェースを使用できます。
Matchmaker SDK を依存関係として追加する
先に進む前に、MatchmakerSDKMatchmakerServerMatchmakerClientYourProjectName.Build.csアクセスしたいプラグインのヘッダーファイルをクラスに加えます。PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });PublicDependencyModuleNames.AddRange(new string[] { "MatchmakerClient", "MatchmakerServer" });PublicDependencyModuleNames.AddRange(new string[] { "Json", "JsonUtilities" });
#include "MatchmakerClientSubsystem.h"#include "MatchmakerServerSubsystem.h"
Matchmaker クライアントサブシステム
Matchmaker クライアントサブシステムが、マッチメイキングとマッチ検出のクライアント部分を制御します。これには、マッチメイキングチケットの作成、削除、ポーリングが含まれています。
Matchmaker クライアントサブシステムには、
UMatchmakerClientSubsystemUMatchmakerClientSubsystemUGameInstanceSubsystemUGameInstanceUWorld* GameWorld = GetWorld();UGameInstance* GameInstance = GameWorld->GetGameInstance();UMatchmakerClientSubsystem* MatchmakerClientSubsystem = GameInstance->GetSubsystem<UMatchmakerClientSubsystem>();
CreateTicket
CreateTicket()Players// Create Players arrayTArray<FMatchmakerPlayer> Players;// Create player definitionFMatchmakerPlayer SamplePlayer;SamplePlayer.Id = TEXT("SamplePlayer");// Adding custom player dataTSharedPtr<FJsonObject> CustomData = MakeShared<FJsonObject>();CustomData->SetNumberField("Skill", 100);CustomData->SetStringField("PreferredMap", "Dune");SamplePlayer.CustomData = CustomData;Players.Add(SamplePlayer);// Setup Ticket OptionsFCreateTicketOptions Options;Options.QueueName = TEXT("default-queue");MatchmakerClientSubsystem->CreateTicket(Players, options, Unity::Services::Core::THandler<FCreateTicketResponse>::CreateLambda([this](FCreateTicketResponse Response){ // Your response logic here (response includes Ticket Id)}));
FCreateTicketResponseGetTicketStatus
GetTicketStatus()FTimerDelegate使用するマッチポーリング関数は以下の例のようになります。// Create the Timer Delegate and set the function to callFTimerDelegate PollTicketDelegate = FTimerDelegate::CreateUObject(this, &UMyCustomClass::PollTicket, Response.TicketId);// Start the Timer that runs every 5 seconds, cache PollTicketTimerHandler to use for stopping the timer later GEngine->GameViewport->GetWorld()->GetTimerManager().SetTimer(PollTicketTimerHandle, PollTicketDelegate, 5, true);
void UMyCustomClass::PollTicket(FGuid TicketId){ MatchmakerClientSubsystem->GetTicketStatus(TicketId, THandler<FGetTicketStatusResponse>::CreateLambda([this, TicketId](FGetTicketStatusResponse Response) { if (Response.bWasSuccessful) { FString TicketIdStr = *TicketId.ToString(EGuidFormats::DigitsWithHyphens).ToLower(); switch (Response.Status) { case StatusEnum::Failed: UE_LOG(LogTemp, Log, TEXT("polling for ticket has failed, response was: %s"), *Response.ErrorMessage); break; case StatusEnum::Timeout: UE_LOG(LogTemp, Log, TEXT("polling for ticket has timed out, response was: %s"), *Response.ErrorMessage); break; case StatusEnum::InProgress: UE_LOG(LogTemp, Log, TEXT("polling for ticket %s is still in progress."), *TicketId.ToString(EGuidFormats::DigitsWithHyphens).ToLower()); return; case StatusEnum::Found: UE_LOG(LogTemp, Log, TEXT("polling for ticket has completed, match found with ip: %s"), *Response.Ip); break; default: UE_LOG(LogTemp, Log, TEXT("unknown status received for ticket: %s), *TicketId.ToString(EGuidFormats::DigitsWithHyphens).ToLower()); break; } // If we made it this far, we got a status other than InProgress so we can end the polling timer. GEngine->GameViewport->GetWorld()->GetTimerManager().ClearTimer(PollTicketTimerHandle); // Delete ticket here } else { UE_LOG(LogTemp, Log, TEXT("Failed to poll Ticket status with ticket ID: %s"), *TicketId.ToString(EGuidFormats::DigitsWithHyphens).ToLower()); } }));}
FGetTicketStatusResponseDeleteTicket
マッチメイキングチケットを削除してマッチメイキングをキャンセルするには、DeleteTicket()FDeleteTicketResponseMatchmakerClientSubsystem->DeleteTicket(TicketId, Unity::Services::Core::THandler<FDeleteTicketResponse>::CreateLambda([](FDeleteTicketResponse Response){ // Your response logic here}));
FDeleteTicketResponseMatchmaker サーバーサブシステム
Matchmaker サーバーサブシステムが、マッチメイキングのサーバー部分を制御します。これには、バックフィルチケットの作成、承認、削除、更新が含まれています。UMatchmakerServerSubsystemUWorld* GameWorld = GetWorld();UGameInstance* GameInstance = GameWorld->GetGameInstance();UMatchmakerServerSubsystem* MatchmakerServerSubsystem = GameInstance->GetSubsystem<UMatchmakerServerSubsystem>();
詳細については、割り当てペイロード を参照してください (
GetPayloadAllocation()CreateBackfillTicket
1 人または複数のプレイヤーが満員のマッチから退出したときに、新しいバックフィルチケットを作成する必要があります。また、サーバーは空のスロットを埋める必要があります。サーバーに新しいバックフィルチケットを作成するには、CreateBackfillTicket()// Setup Backfill Ticket OptionsFCreateBackfillTicketOptions CreateBackfillTicketOptions;CreateBackfillTicketOptions.Connection = TEXT("35.245.90.171:9000");CreateBackfillTicketOptions.QueueName = TEXT("default-queue");// Create Match PropertiesFMatchProperties MatchProperties;FGuid BackfillTicketId = FGuid::NewGuid();MatchProperties.BackfillTicketId = BackfillTicket.Id;MatchProperties.Region = TEXT("aaaaaaaa-1111-bbbb-2222-cccccccccccc");// Create PlayerFMatchmakerPlayer Player;Player.Id = FGuid::NewGuid().ToString();FQosResult QosResult;QosResult.Latency = 20;QosResult.PacketLoss = 5;QosResult.Region = TEXT("aaaaaaaa-1111-bbbb-2222-cccccccccccc");Player.QoSResults.Add(QosResult);MatchProperties.Players.Add(Player);// Create TeamFMatchmakerTeam Team;Team.TeamName = TEXT("Red");FGuid TeamId = FGuid::NewGuid();Team.TeamId = TeamId.ToString(EGuidFormats::DigitsWithHyphens);Team.PlayerIds.Add(Player.Id);MatchProperties.Teams.Add(Team);CreateBackfillTicketOptions.Properties.MatchProperties = MatchProperties;MatchmakerServerSubsystem->CreateBackfillTicket(CreateBackfillTicketOptions, Unity::Services::Core::THandler<FCreateBackfillTicketResponse>::CreateLambda([this, Player, Team](FCreateBackfillTicketResponse CreateResponse){ // Your response logic here}));
FCreateBackfillTicketResponseApproveBackfillTicket
作成後のバックフィルチケットを承認するには、ApproveBackfillTicket()MatchmakerServerSubsystem->ApproveBackfillTicket(BackfillTicketId, Unity::Services::Core::THandler<FApproveBackfillTicketResponse>::CreateLambda([this](FApproveBackfillTicketResponse ApproveResponse){ // Your response logic here}));
FApproveBackfillTicketResponseDeleteBackfillTicket
マッチが満員になり、サーバーで新しいプレイヤーを受け付ける必要がなくなった時点で、バックフィルチケットを削除します。マッチが終了し、サーバーに新しいプレイヤーを受け入れたくなくなった後も、同じ処理を行う必要があります。サーバーへのバックフィルを停止するには、DeleteBackfillTicket()MatchmakerServerSubsystem->DeleteBackfillTicket(BackfillTicketId, Unity::Services::Core::THandler<FDeleteBackfillTicketResponse>::CreateLambda([this](FDeleteBackfillTicketResponse DeleteResponse){ // Handle response here}));
FDeleteBackfillTicketResponseUpdateBackfillTicket
サーバーの現在のバックフィルチケットを更新するには、UpdateBackfillTicket()Unity では、先に// From ApproveFBackfillTicket BackfillTicket;FGuid BackfillTicketId = FGuid::Parse(ApproveResponse.BackfillTicket.Id, BackfillTicketId);FBackfillTicket BackfillTicket = ApproveResponse.BackfillTicket;// Setup MatchPropertiesFMatchProperties MatchProperties;MatchProperties.BackfillTicketId = BackfillTicket.Id; // Could be retrieved in Payload allocation's MatchPropertiesMatchProperties.Region = TEXT("aaaaaaaa-1111-bbbb-2222-cccccccccccc"); // Could be retrieved in Payload allocation's MatchProperties// Add a new player to the backfill ticketFMatchmakerPlayer NewPlayer;NewPlayer.Id = TEXT("NewPlayer");TSharedPtr<FJsonObject> CustomData = MakeShared<FJsonObject>();CustomData->SetNumberField("Skill", 100);CustomData->SetStringField("PreferredMap", "Dune");NewPlayer.CustomData = CustomData;BackfillTicket.Properties.Players.Add(NewPlayer);BackfillTicket.Properties.[0].PlayerIds.Add(NewPlayer.Id);// Remove a Player from the backfill ticketFString PlayerIdToRemove = TEXT("SamplePlayer");for (FMatchmakerPlayer Player : BackfillTicket.Properties.Players){ if (Player.Id == PlayerIdToRemove) { BackfillTicket.Properties.Players.Remove(Player); break; }}if (BackfillTicket.Properties.Teams[0].PlayerIds.Contains(PlayerIdToRemove)){ BackfillTicket.Properties.Teams[0].PlayerIds.Remove(PlayerIdToRemove);}// Call to update backfill ticketMatchmakerServerSubsystem->UpdateBackfillTicket(BackfillTicketId, BackfillTicket, Unity::Services::Core::THandler<FUpdateBackfillTicketResponse>::CreateLambda([this, BackfillTicketId](FUpdateBackfillTicketResponse UpdateResponse){ // Handle Response here}));
ApproveBackfillTicketApproveBackfillTicketBackfillTicketUpdateBackfillTicketFUpdateBackfillTicketResponseTHandler の使用
この SDK には、ブループリントに対応するカスタムデリゲートが含まれます。THandler の使用方法は、通常の Unreal Engine デリゲートと似ています。 以下のコードスニペットに、インライン応答を使用して呼び出しを行う方法を示します。Matchmaker::THandler<FCreateTicketResponse>::CreateLambda([ResponseDelegate](FCreateTicketResponse Response){ if (Response.bWasSuccessful) { UE_LOG(LogMatchmakerSDK, Log, TEXT("Successfully retrieved Ticket ID: %s"), *Response.TicketId); } else { UE_LOG(LogMatchmakerSDK, Error, TEXT("Failed to retrieve Ticket ID: %s"), *Response.ErrorMessage); } ResponseDelegate.ExecuteIfBound(Response);}));