サブシステムの実装 - ゲームクライアント統合 - (Unreal Engine モジュール)
Last updated on February 4, 2026
注釈:本資料はAI技術を用いて翻訳されています。
サンプルマッチメイキングバックエンドサービスについて
実装をより理解するために、まずゲームクライアントとサンプルマッチメイキングバックエンドサービスサーバー間の通信を確認してください。
サブシステムの展開
このチュートリアルに従うために、CustomMatchmakingSubsystem_Starter という Game Instance Subsystem が用意されています。このクラスはリソースセクションで入手でき、以下のファイルで構成されています:
- ヘッダーファイル:
/Source/AccelByteWars/TutorialModules/Play/CustomMatchmaking/CustomMatchmakingSubsystem_Starter.cpp - CPP ファイル:
/Source/AccelByteWars/TutorialModules/Play/CustomMatchmaking/CustomMatchmakingSubsystem_Starter.h
CustomMatchmakingSubsystem_Starter クラスには、いくつかの機能が提供されています。
- マッチメイキングイベントに関数をバインドするために後で使用されるデリゲート。
public:
FOnMatchmakingStarted OnMatchmakingStartedDelegates;
FOnMatchmakingStopped OnMatchmakingStoppedDelegates;
FOnMatchmakingError OnMatchmakingErrorDelegates;
FOnMatchmakingMessageReceived OnMatchmakingMessageReceivedDelegates;
- WebSocket 参照。Byte Wars は、このモジュールに Unreal Engine の組み込み WebSocket ハンドラーを使用します。
private:
TSharedPtr<IWebSocket> WebSocket;
- WebSocket セットアップ関数。実際の WebSocket セットアップはこのスターターファイルにはまだ存在しません。CPP ファイルで確認できるコードは、起動引数または設定ファイルからサーバー URL を取得するロジックです。
private:
// ...
void SetupWebSocket();
- WebSocket クリーンアップ関数。後で WebSocket をクリーンアップするために使用するダミー関数です。
private:
// ...
void CleanupWebSocket();
- カスタムエラーメッセージを保存する変数。これはエラーをよりユーザーフレンドリーにするためです。WebSocket を閉じる際にカスタムエラーメッセージを渡しても、対応するデリゲートが同じエラーメッセージを渡すわけではありません。そのため、この変数があります。
private:
// ...
FString PendingDisconnectReason = TEXT("");
- ペイロード無効エラーをスローする関数。これは、マッチメイキングサービスがゲームが期待するものではないペイロードを送信した場合を処理するためです。その場合、ゲームは WebSocket 接続を閉じます。
void UCustomMatchmakingSubsystem_Starter::ThrowInvalidPayloadError()
{
UE_LOG_CUSTOMMATCHMAKING(Warning, TEXT("Unexpected message format was received from the Matchmaking service, closing websocket"))
PendingDisconnectReason = TEXT_WEBSOCKET_PARSE_ERROR;
WebSocket->Close(WEBSOCKET_ERROR_CODE_UNEXPECTED_MESSAGE, TEXT_WEBSOCKET_PARSE_ERROR);
}
スターターサブシステムの他に、/Source/AccelByteWars/TutorialModules/Play/CustomMatchmaking/CustomMatchmakingModels.h ファイルには、いくつかの定数、デリゲート宣言、構造体宣言、およびヘルパーも用意されています。
- テキストと文字列定数。
#define WEBSOCKET_ERROR_CODE_UNEXPECTED_MESSAGE (int) 4001
#define WEBSOCKET_FAILED_GENERIC_MESSAGE FString(TEXT("connect failed"))
#define CUSTOM_MATCHMAKING_CONFIG_SECTION_URL FString(TEXT("CustomMatchmaking"))
#define CUSTOM_MATCHMAKING_CONFIG_KEY_URL FString(TEXT("CustomMatchmakingUrl"))
#define DEFAULT_MATCHMAKING_CONFIG_URL TEXT("ws://127.0.0.1:8080")
#define WEBSOCKET_PROTOCOL TEXT("ws")
#define TEXT_LOADING_TRAVELLING FString(TEXT("Travelling to server"))
#define TEXT_LOADING_FINDING_MATCH FString(TEXT("Finding Match"))
#define TEXT_LOADING_REQUEST FString(TEXT("Requesting"))
#define TEXT_LOADING_CANCEL FString(TEXT("Canceling"))
#define TEXT_ERROR_CANCELED FString(TEXT("Canceled"))
#define TEXT_WEBSOCKET_ERROR_GENERIC FString(TEXT("Connect failed.\nMake sure the Matchmaking server is running, reachable, and the address and port is set properly"))
#define TEXT_WEBSOCKET_PARSE_ERROR FString(TEXT("Received invalid payload format from Matchmaking server. Make sure you are running a compatible version."))
- デリゲート宣言。
DECLARE_MULTICAST_DELEGATE(FOnMatchmakingStarted)
DECLARE_MULTICAST_DELEGATE_OneParam(FOnMatchmakingStopped, const FString& /*Reason*/)
DECLARE_MULTICAST_DELEGATE_OneParam(FOnMatchmakingMessageReceived, const FMatchmakerPayload& /*Payload*/)
DECLARE_MULTICAST_DELEGATE_OneParam(FOnMatchmakingError, const FString& /*ErrorMessage*/)
- サンプルマッチメイキングバックエンドサービスから受信したメッセージを表す構造体と列挙型。USTRUCT と UPROPERTY は、Unreal Engine の組み込み関数を利用して JSON を構造体に変換するために使用されます(
FJsonObjectConverter::JsonObjectStringToUStruct関数)。
UENUM(BlueprintType)
enum class EMatchmakerPayloadType : uint8
{
OnFindingMatch,
OnMatchFound,
OnServerClaimFailed,
OnServerReady
};
USTRUCT()
struct FMatchmakerPayload
{
GENERATED_BODY()
public:
UPROPERTY()
EMatchmakerPayloadType Type;
UPROPERTY()
FString Message;
};
マッチメイキングの実装
CustomMatchmakingSubsystem_Starterヘッダーファイルを開き、以下の関数宣言を追加します。UE の WebSocket インターフェースには、OnConnected、OnClosed、OnMessage、OnConnectionErrorの 4 つのイベントがあります。ここで宣言された関数は、これらの各イベントがトリガーされたときに何が起こるかを処理します。
private:
// ...
UFUNCTION()
void OnConnected() const;
UFUNCTION()
void OnClosed(int32 StatusCode, const FString& Reason, bool WasClean);
UFUNCTION()
void OnMessage(const FString& Message);
UFUNCTION()
void OnError(const FString& Error) const;
CustomMatchmakingSubsystem_StarterCPP ファイルを開き、OnConnected関数を定義します。この関数は、接続が正常に確立された後に何が起こるかを処理します。この場合、ゲームは単にデリゲートをトリガーして、他のオブジェクトが何かを実行できるようにします。
void UCustomMatchmakingSubsystem_Starter::OnConnected() const
{
UE_LOG_CUSTOMMATCHMAKING(Verbose, TEXT("Websocket connected"))
OnMatchmakingStartedDelegates.Broadcast();
}
OnClosed関数を定義します。これは、接続が閉じられた後に何が起こるかを処理します。ここでは、CleanupWebSocket関数を呼び出します。
void UCustomMatchmakingSubsystem_Starter::OnClosed(int32 StatusCode, const FString& Reason, bool WasClean)
{
UE_LOG_CUSTOMMATCHMAKING(Verbose, TEXT("Websocket closed: (%d) %s"), StatusCode, *Reason)
// Modify the error message to make it more user-friendly
const FString ModifiedReason = PendingDisconnectReason.IsEmpty() ? TEXT_WEBSOCKET_ERROR_GENERIC : PendingDisconnectReason;
OnMatchmakingStoppedDelegates.Broadcast(ModifiedReason);
CleanupWebSocket();
}
OnMessage関数を定義します。この関数は、ゲームがマッチメイキングサービスからメッセージを受信したときに呼び出されます。サンプルマッチメイキングバックエンドサービスの図に示されているように、マッチメイキングサーバーは JSON 形式の文字列としてメッセージを送信し、4 つの可能なtype値があります:OnFindingMatch、OnMatchFound、OnServerReady、OnServerClaimFailed。ほとんどのメッセージタイプでは、ゲームは単にデリゲートをトリガーしてメッセージを渡します。ただし、OnServerReadyの場合、デリゲートをトリガーすることに加えて、ゲームはメッセージで提供された IP アドレスへの接続も試みます。
void UCustomMatchmakingSubsystem_Starter::OnMessage(const FString& Message)
{
UE_LOG_CUSTOMMATCHMAKING(Verbose, TEXT("Websocket message received: %s"), *Message)
if (Message.IsEmpty())
{
UE_LOG_CUSTOMMATCHMAKING(VeryVerbose, TEXT("Message is empty, skipping"))
return;
}
// Parse message
FMatchmakerPayload Payload;
// Safety in case the received message is different than expected
if (!FJsonObjectConverter::JsonObjectStringToUStruct<FMatchmakerPayload>(Message, &Payload))
{
ThrowInvalidPayloadError();
return;
}
// Notify
OnMatchmakingMessageReceivedDelegates.Broadcast(Payload);
// Travel if server is ready
if (Payload.Type == EMatchmakerPayloadType::OnServerReady)
{
// Use FInternetAddr to check whether this is a valid IPv4 or IPv6
const TSharedPtr<FInternetAddr> ServerAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
bool bIsValid = false;
ServerAddress->SetIp(*Payload.Message, bIsValid);
if (!bIsValid)
{
ThrowInvalidPayloadError();
return;
}
// Trigger travel
AAccelByteWarsPlayerController* PC = Cast<AAccelByteWarsPlayerController>(GetWorld()->GetFirstPlayerController());
if (!PC)
{
UE_LOG_CUSTOMMATCHMAKING(Warning, TEXT("Player Controller is not AAccelByteWarsPlayerController, cancelling travel"))
return;
}
const FString Address = ServerAddress->ToString(true);
PC->DelayedClientTravel(Address, ETravelType::TRAVEL_Absolute);
}
}
OnError関数を定義します。これは、WebSocket が失敗したときに何が起こるかを処理します。ここでは、ゲームは単にデリゲートをトリガーして、他のオブジェクトが何かを実行できるようにします。
void UCustomMatchmakingSubsystem_Starter::OnError(const FString& Error) const
{
UE_LOG_CUSTOMMATCHMAKING(Verbose, TEXT("Websocket error: %s"), *Error)
// Use a generic message since UE's built in error message are not clear enough
OnMatchmakingErrorDelegates.Broadcast(TEXT_WEBSOCKET_ERROR_GENERIC);
}
CustomMatchmakingSubsystem_Starterヘッダーファイルを開き、以下の関数宣言を追加します。
public:
// ...
void StartMatchmaking();
void StopMatchmaking();
CustomMatchmakingSubsystem_StarterCPP ファイルを開き、StartMatchmaking関数を定義します。サンプルマッチメイキングバックエンドサービスの図を参照すると、マッチメイキングを開始するには、ゲームは単に WebSocket 経由でサーバーに接続する必要があります。
void UCustomMatchmakingSubsystem_Starter::StartMatchmaking()
{
// In this sample, connecting to the websocket will immediately start the matchmaking
SetupWebSocket();
WebSocket->Connect();
}
SetupWebSocket関数に移動し、関数の最後に以下のコードを追加します。ここでは、WebSocket を構築し、関数を WebSocket イベントに接続するという 2 つのことを行っています。
void UCustomMatchmakingSubsystem_Starter::SetupWebSocket()
{
// ...
// WebSocket setup
UE_LOG_CUSTOMMATCHMAKING(Verbose, TEXT("WebSocket target URL: %s"), *ServerUrl)
WebSocket = FWebSocketsModule::Get().CreateWebSocket(ServerUrl, WEBSOCKET_PROTOCOL);
// Bind events
WebSocket->OnConnected().AddUObject(this, &ThisClass::OnConnected);
WebSocket->OnConnectionError().AddUObject(this, &ThisClass::OnError);
WebSocket->OnClosed().AddUObject(this, &ThisClass::OnClosed);
WebSocket->OnMessage().AddUObject(this, &ThisClass::OnMessage);
}
StopMatchmaking関数を定義します。このサンプルマッチメイキングバックエンドサービスでは、マッチメイキングの停止は単に WebSocket 接続を閉じることで行われます。
void UCustomMatchmakingSubsystem_Starter::StopMatchmaking()
{
// Cancel the matchmaking by disconnecting from the websocket
if (!WebSocket)
{
UE_LOG_CUSTOMMATCHMAKING(Verbose, TEXT("Websocket is null, operation cancelled"))
return;
}
PendingDisconnectReason = TEXT_ERROR_CANCELED;
WebSocket->Close();
}
CleanupWebSocket関数に移動し、以下のコードを追加します。この関数は、現在の WebSocket オブジェクトをクリーンアップし、すべてのイベントをアンバインドし、参照を破棄します。
void UCustomMatchmakingSubsystem_Starter::CleanupWebSocket()
{
PendingDisconnectReason = TEXT("");
// Unbind events
WebSocket->OnConnected().RemoveAll(this);
WebSocket->OnConnectionError().RemoveAll(this);
WebSocket->OnClosed().RemoveAll(this);
WebSocket->OnMessage().RemoveAll(this);
WebSocket = nullptr;
}
リソース
- このチュートリアルセクションで使用されているファイルは、Byte Wars Unreal GitHub リポジトリで入手できます。
- AccelByteWars/Source/AccelByteWars/TutorialModules/Play/CustomMatchmaking/CustomMatchmakingSubsystem_Starter.cpp
- AccelByteWars/Source/AccelByteWars/TutorialModules/Play/CustomMatchmaking/CustomMatchmakingSubsystem_Starter.h
- AccelByteWars/Source/AccelByteWars/TutorialModules/Play/CustomMatchmaking/CustomMatchmakingModels.h