マッチメイキングをゲームクライアントに統合する
注釈:本資料はAI技術を用いて翻訳されています。
この記事では、Unreal Engineゲームでのマッチメイキングの設定について説明します。Unityを使用している場合は、Unityマッチメイキング統合記事を参照してください。
概要
マッチメイキングは、2人以上のプレイヤーがマッチのために評価され、一緒にプレイできるようにゲームセッションに参加するプロセスです。マッチメイキングプロセス中にAccelByte Gaming Services(AGS)マッチメイキングが相互作用するいくつかのコンポーネントがあります。
-
Session Template: セッションが作成される際の特性を定義します。これには、参加可能性、使用するゲームサーバーデプロイメント、プレイヤー要件、チーム構成などが含まれます。
-
Match Ticket: ソロプレイヤーまたはパーティによるマッチメイキングのリクエストを定義し、評価用にプレイヤー情報が添付されます。
-
Backfill Ticket: マッチチケットと似ていますが、マッチルールセットで自動バックフィルが有効になっている場合にのみ作成されます。この場合、2人以上のプレイヤーがマッチングされると、彼らはセッションに参加し、最小プレイヤー数がセッションに接続するまでマッチを見つけ続けるためにバックフィルチケットがAGSマッチメイキングに送信されます。
-
Match Pool: 有効なマッチのためにサービスによって評価できるマッチチケットのコレクションを定義します。チケットは、選択されたゲームモードと設定(該当する場合)に基づいて同じプールに入ります。
-
Match Ruleset: チケットが有効なマッチを構成するかどうかを判断するためにデフォルトのマッチ関数によって使用される属性と比較基準を定義します。マッチ関数がオーバーライドされている場合でも、評価に必要なAGS Statisticsに保存されている属性でルールセットを設定する必要があります。
-
Match Function: サービスがマッチチケットを評価するために使用するロジックを定義します。デフォルトでは、サービスは関連するマッチルールセットで定義された基準を使用します。
この記事では、Unreal OnlineSubsystem(OSS) V2プラグインを使用して、AGSマッチメイキングをUnrealゲームクライアントに統合する方法を説明します。
目標
この記事は、マッチメイキングプレイヤー体験フローの理解を提供し、以下の統合方法を示すことを目的としています:
- ソロプレイヤーとパーティのマッチメイキングの開始
- マッチが見つかる前のマッチメイキングのキャンセル
- マッチ結果のリスニングと処理
- ゲームセッション招待のリスニングとセッションへの参加
前提条件
この記事のすべての手順を完了するには、以下が必要です:
-
AGS Lobby、Session、Matchmakingに関する知識
-
Online Subsystem(OSS)を含むUnreal Engineの基本的な理解
-
ゲームプロジェクトにインストールされたUnreal OSS V2プラグイン
-
AGS Admin Portalへのアクセス
-
作成および設定されたセッションテンプレート、マッチルールセット、マッチプール
-
DefaultEngine.iniファイルに以下を追加することにより、AccelByte OSSでSessions V2を有効化:[OnlineSubsystemAccelByte]
bEnableV2Sessions=true -
Admin PortalでゲームクライアントにAGSマッチメイキングとSession V2の必要な権限を設定
-
AGSバックエンドで認証され、AGS Lobbyに接続されたゲームクライアント
ゲームプロジェクトにマッチメイキングを開始する機能を統合するには、いくつかのOSSコンポーネントに精通している必要があります:
-
Session Interface: マッチメイキングとセッション管理を実行するために使用される機能を提供します。
-
Session Search Handle: セッション検索の結果を保存し、マッチングが成功した場合に返されるゲームセッションを保存するためにマッチメイキング中に必要です。
-
Matchmaking Callback Functions: マッチメイキング開始やマッチメイキング完了などの特定のマッチメイキングイベントをリスニングします。
-
Join Session Callback Functions: セッション破棄やセッション参加などの特定のセッションイベントをリスニングします。
マッチメイキングフローの実装
実装は、マッチメイキングフローの概要で説明されている高レベルのフローに従います。
マッチメイキングを開始する
マッチメイキングを開始する予定の関数で、AGS OSSからSession Interfaceを取得する必要があります。マッチメイキングをリクエストするために使用するFOnlineSessionAccelBytePtr型のカスタムAGS Session Interfaceがあることに注意してください。
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
if (!ensure(Subsystem != nullptr))
{
return;
}
const FOnlineSessionAccelBytePtr SessionInterface = StaticCastSharedPtr<FOnlineSessionV2AccelByte>(Subsystem->GetSessionInterface());
if (!ensure(SessionInterface.IsValid()))
{
return;
}
後でコールバック結果を処理するためにアクセスする必要があるため、Session Interfaceをクラスメンバーとして保存することをお勧めします。
ゲームクライアントのPlayer IDを取得して、マッチメイキングを開始するリクエストの一部としてPlayer Controller IDを渡すために後で使用できるようにする必要があります。Player Controller IDは、コールバック結果を処理する際にも後で使用されます。
const FUniqueNetIdPtr LocalPlayerId = GetUniquePlayerId();
if (!ensure(LocalPlayerId.IsValid()))
{
return false;
}
マッチが正常に見つかった場合にマッチメイキングプロセス中に作成されたセッション結果を保存するために使用するSession Search Handle FOnlineSessionSearchを作成する必要があります。Session Search Handleを作成する際、次のパラメータでクエリ設定を設定する必要があります:
- Player Controller ID: マッチメイキング中にマッチチケットが送信されるプレイヤーのOSS ID。
- Match Pool Session Settings: マッチメイキング中に使用されるOSSセッション設定:
SETTING_SESSION_MATCHPOOL。これを渡すことで、次のパラメータとして提供するMatch Pool Nameで更新されます。 - Match Pool Name: 指定されたゲームモードの前提条件の一部として定義したマッチプールの名前。これにより、AGSマッチメイキングに新しく作成されたマッチチケットをそのマッチプールに追加して評価するよう通知します。
- Comparison Operator: セッション検索の一部として使用されるOSS演算子、この場合:
EOnlineComparisonOp::Equals。
// マッチメイキング用の新しい検索ハンドルインスタンスを作成します。重要:以下に示すように、SETTING_SESSION_MATCHPOOLで検索するマッチプールを設定する必要があります。
TSharedRef<FOnlineSessionSearchAccelByte> MatchmakingSearchHandle = MakeShared<FOnlineSessionSearchAccelByte>();
MatchmakingSearchHandle->QuerySettings.Set(SETTING_SESSION_MATCHPOOL, FString(TEXT("YOUR_MATCHPOOL_NAME_GOES_HERE")), EOnlineComparisonOp::Equals);
Session Search Handleをクラスメンバーとして保存し、その型を保持することを確認してから、マッチが正常に見つかった後に返された結果を割り当てることをお勧めします。
マッチメイキングが完了したときにトリガーされるマッチ結果をリスニングするために、FOnMatchmakingCompleteDelegateコールバックデリゲートを登録する必要があります。
- Session Name: マッチが成功した場合に作成されたゲームセッションの名前。
- Success Value: マッチメイキングがマッチを正常に見つけたかどうかを示すブール値。
// 戻り値の型がvoidで、これらのパラメータを持つ関数をバインドします:
// FName SessionName, bool bWasSuccessful
const FOnMatchmakingCompleteDelegate OnMatchmakingCompleteDelegate = /* ラムダまたはクラスメソッドにバインド */;
SessionInterface->AddOnMatchmakingCompleteDelegate_Handle(OnMatchmakingCompleteDelegate);
上記を取得したら、Session InterfaceからStartMatchmaking()を呼び出してマッチメイキングの開始をリクエストできます。この関数は次のパラメータを取ります:
- Player Controller ID: マッチメイキング中にマッチチケットが送信されるプレイヤーのOSS ID。
- Session Name: マッチメイキングが成功した場合に作成されるセッションの名前。通常、
NAME_GameSessionを渡します。 - Session Settings: AGS Sessionがゲームセッションを作成するために使用すべきセッション設定:
FOnlineSessionSettings()。この場合、空のオブジェクトを渡すことで、AGS Sessionに設定を割り当てさせます。 - Session Search Handle: マッチメイキングが成功した場合に作成されるゲームセッションを保存するために、このセクションの前半で作成したSession Search Handle。
StartMatchmaking()へのリクエストが行われ、呼び出しがtrueを返すと仮定すると、将来のアクセスのために、このセクションの前半で定義したSession Search Handleをクラスメンバーにバインドする必要があります。StartMatchmaking()がfalseを返す場合、それはAGSマッチメイキングへの呼び出しに問題があったことを示します。
if (SessionInterface->StartMatchmaking(
USER_ID_TO_MATCHMAKING_USER_ARRAY(LocalPlayerId.ToSharedRef()),
NAME_GameSession,
FOnlineSessionSettings(),
MatchmakingSearchHandle,
OnStartMatchmakingCompleteDelegate))
{
// Update the current search result handle class member with the search handle passed to AGS Matchmaking.
CurrentMatchmakingSearchHandle = MatchmakingSearchHandle;
}
OnlineSubsystemV2では、パーティに参加している場合、StartMatchmaking呼び出しは、作成時にマッチチケットの一部として添付されるPartyIDを自動的に送信します。
マッチメイキング結果からセッションを除外する
マッチメイキングサービスでは、プレイヤーのセッション履歴を記録することで、マッチメイキング結果からセッションを除外できます。これらのセッション履歴記録と除外オプションは、ゲーム内トグルとして利用可能で、プレイヤーが好みに応じてオン/オフを切り替えることができます。ゲームで次の除外機能を有効にできます:
- タイプ1:特定のセッションを除外
FAccelByteModelsGameSessionExcludedSession::CreateExclusionList(TSet<FString> SetOfExcludedGameSessionId); - タイプ2:すべての過去のセッションを除外
FAccelByteModelsGameSessionExcludedSession::CreateExclusionEntireSessionMemberPastSession(); - タイプ3:特定の数の最新セッションを除外
FAccelByteModelsGameSessionExcludedSession::CreateExclusionCount(ExcludedPastSessionCount); - タイプ4:除外なし
FAccelByteModelsGameSessionExcludedSession::CreateNoExclusion();
これらの機能を有効にする方法の詳細については、セッション履歴の記録とセッションの除外ページを参照してください。
ゲームセッションに参加する
マッチメイキングが完了すると、マッチメイキングを開始する前にバインドしたOnMatchmakingCompleteDelegateが発火し、次の手順に従って結果を処理できます。
Session Search HandleのSearchResultsメンバー配列に保存されているゲームセッション結果を取得する必要があります。配列が空の場合は、トラブルシューティングを参照してください。
// 続行する前に、配列に有効なセッション検索結果があることを確認します
if (!CurrentMatchmakingSearchHandle->SearchResults.IsValidIndex(0))
{
return false;
}
FOnlineSessionSearchResult MatchResult = CurrentMatchmakingSearchHandle->SearchResults[0];
EOnlineSessionTypeAccelByte SessionType = SessionInterface->GetSessionTypeFromSettings(MatchResult.Session.SessionSettings);
if (SessionType != EOnlineSessionTypeAccelByte::GameSession)
{
return false;
}
プレイヤーがすでにゲームセッションにいるかどうかを確認する必要があります。その場合、マッチメイキングを通じて返された新しいセッションに参加できるように、それを破棄する必要があります。結果をリスニングするためにFOnDestroySessionCompleteDelegateコールバックデリゲートを登録できます。
// すでにゲームセッションがあるかどうかを確認します。ある場合は、このセッションに参加するために破棄します。
if (SessionInterface->GetNamedSession(NAME_GameSession) != nullptr)
{
const FOnDestroySessionCompleteDelegate OnDestroySessionForJoinCompleteDelegate = FOnDestroySessionCompleteDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnDestroySessionForJoinComplete, Session);
return SessionInterface->DestroySession(NAME_GameSession, OnDestroySessionForJoinCompleteDelegate);
}
参加リクエストが完了したときにトリガーされる参加結果をリスニングするために、FOnJoinSessionCompleteDelegateコールバックデリゲートを登録する必要があります。その時点で、ゲームサーバーへの参加をリクエストできます。コールバック関数のサンプルコードについては、この記事のゲームホストへの参加セクションを参照してください。
// 指定されたセッションに参加するためのデリゲートを登録します
const FOnJoinSessionCompleteDelegate OnJoinSessionCompleteDelegate = FOnJoinSessionCompleteDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnJoinSessionComplete);
JoinSessionDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegate);
上記を取得したら、Session InterfaceからJoinSession()を呼び出して、返されたセッションに参加できます。この関数は次のパラメータを取ります:
- Player Controller ID: マッチメイキング中にマッチチケットが送信されるプレイヤーのOSS ID。
- Session Name: マッチメイキングが成功した場合に作成されるゲームセッションの名前。
- Session: AGS Sessionが後でアクセスするためにゲームセッション情報を割り当てるOSS Sessionオブジェクト。
SessionInterface->JoinSession(LocalPlayerId.ToSharedRef().Get(), NAME_GameSession, Session);
- プレイヤーがセッションから退出または切断した場合、AGSマッチメイキングを通じて同じセッションに再参加することはできません。プレイヤーはAGS Sessionの
JoinAPIを使用する必要があります。セッションの参加可能性がOPENに設定されているか、INVITE_ONLYに設定されている場合、Session::JoinGameSessionを呼び出してセッションに再参加できます。 - プレイヤーがまだ
DISCONNECTEDステータスの場合、AGS Lobbyに再接続すると、ステータスはCONNECTEDに戻ります。この場合、プレイヤーはSession::GetMyGameSessionsを使用するか、ゲームIDがある場合はSession::GetGameSessionDetailsを使用してゲームセッションの詳細を取得できます。
OnMatchmakingComplete結果をリスニングするデリゲートとして使用できるコールバック関数の完全な例を次に示します:
void OnMatchmakingCompleteDelegate(FName SessionName, bool bWasSuccessful)
{
if (SessionName != NAME_GameSession)
{
return;
}
EOnlineSessionTypeAccelByte SessionType = SessionInterface->GetSessionTypeFromSettings(MatchResult.Session.SessionSettings);
if (SessionType != EOnlineSessionTypeAccelByte::GameSession)
{
return false;
}
// Ensure that you have a valid session search result in the array before continuing
if (!CurrentMatchmakingSearchHandle->SearchResults.IsValidIndex(0))
{
return false;
}
FOnlineSessionSearchResult MatchResult = CurrentMatchmakingSearchHandle->SearchResults[0];
// Check if you already have a game session that you are in. If so, destroy it to join this one.
if (SessionInterface->GetNamedSession(NAME_GameSession) != nullptr)
{
const FOnDestroySessionCompleteDelegate OnDestroySessionForJoinCompleteDelegate = FOnDestroySessionCompleteDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnDestroySessionForJoinComplete, Session);
return SessionInterface->DestroySession(NAME_GameSession, OnDestroySessionForJoinCompleteDelegate);
}
// Register a delegate for joining the specified session
const FOnJoinSessionCompleteDelegate OnJoinSessionCompleteDelegate = FOnJoinSessionCompleteDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnJoinSessionComplete);
JoinSessionDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegate);
const FUniqueNetIdPtr LocalPlayerId = GetUniquePlayerId();
if (!ensure(LocalPlayerId.IsValid()))
{
return false;
}
return SessionInterface->JoinSession(LocalPlayerId.ToSharedRef().Get(), NAME_GameSession, Session);
}
ゲームホストに参加する
ゲームセッションへの参加が完了すると、セッションへの参加をリクエストする前にバインドしたOnJoinSessionCompleteが発火し、次の手順に従って結果を処理できます。
デリゲートに渡された結果enumを確認して、参加リクエストが正常に完了し、ゲームセッションに参加したかどうかを判断する必要があります。
if (Result != EOnJoinSessionCompleteResult::Success)
{
return;
}
成功した場合、ゲームセッションに参加しており、GetResolvedConnectString()を呼び出すことで、Session Interfaceから関連するホスト接続を抽出できます。この関数は次のパラメータを取ります:
- Session Name: マッチメイキングが成功した場合に作成されるゲームセッションの名前。
- TravelURL: セッションがホストに接続されている場合、接続文字列が含まれます。
- Game Port: 接続用のホストポート。
接続文字列をリクエストした後、TravelURLには有効な接続文字列が含まれるか、空になります。有効な接続文字列が含まれている場合、ゲームセッションが接続されており、その文字列を使用してプレイヤーをホストに接続できます。
空の場合、ゲームセッションはまだ接続を待機しており、ホスト参加結果をリスニングし、ゲームセッションがホストに正常に接続するのを待つために、OnSessionServerUpdateコールバックデリゲートを登録する必要があります。
FString TravelUrl{};
if (SessionInterface->GetResolvedConnectString(SessionName, TravelUrl, NAME_GamePort) && !TravelUrl.IsEmpty())
{
// セッションから接続文字列を正常に取得した場合、ここで接続します
}
else
{
// それ以外の場合は、サーバーが起動するのを待つために、OnSessionServerUpdateにデリゲートをバインドします。
const FOnSessionServerUpdateDelegate OnSessionServerUpdateDelegate = FOnSessionServerUpdateDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnSessionServerUpdate);
SessionInterface->AddOnSessionServerUpdateDelegate_Handle(OnSessionServerUpdateDelegate);
}
OnJoinSessionComplete結果をリスニングするデリゲートとして使用できるコールバック関数の完全な例を次に示します:
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if (SessionName != NAME_GameSession)
{
return;
}
if (Result != EOnJoinSessionCompleteResult::Success)
{
return;
}
const FOnlineSessionAccelBytePtr SessionInterface = GetSessionInterface();
check(SessionInterface.IsValid());
// Remove your delegate handler for join session. You will rebind if you join another session
SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionDelegateHandle);
JoinSessionDelegateHandle.Reset();
FNamedOnlineSession* Session = SessionInterface->GetNamedSession(SessionName);
check(Session != nullptr)
TSharedPtr<FOnlineSessionInfoAccelByteV2> SessionInfo = StaticCastSharedPtr<FOnlineSessionInfoAccelByteV2>(Session->SessionInfo);
check(SessionInfo.IsValid());
FString TravelUrl{};
if (SessionInterface->GetResolvedConnectString(SessionName, TravelUrl, NAME_GamePort) && !TravelUrl.IsEmpty())
{
// If you successfully got a connect string from the session, then this is where you would connect to it
}
else
{
// Otherwise, bind a delegate to OnSessionServerUpdate to wait for a server to be spun up. Once this
// delegate is fired, you may call the same GetResolvedConnectString to get the server address to
// connect to.
const FOnSessionServerUpdateDelegate OnSessionServerUpdateDelegate = FOnSessionServerUpdateDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnSessionServerUpdate);
SessionInterface->AddOnSessionServerUpdateDelegate_Handle(OnSessionServerUpdateDelegate);
}
}
追加のマッチメイキング呼び出し
マッチメイキングをキャンセルする
プロセスが完了またはタイムアウトする前にマッチメイキングをキャンセルする必要がある場合、FOnlineSessionV2Accelbyte::CancelMatchmaking()を呼び出し、Player Controller ID、Session Name、およびマッチメイキングの開始をリクエストしたときに提供したNAME_GameSessionを渡すことができます。
マッチチケットにバージョン番号を追加する
AGS Game SDKもOSSも、マッチチケットが送信されるときに自動的にclient_versionを追加しません。
SDKの場合、MatchmakingV2::CreateMatchTicket APIはFAccelByteModelsV2MatchTicketOptionalParams型のOptionals構造体を受け取ります。その中にAttributesという名前のフィールドがあり、そこにclient_versionフィールドを追加できます。以下のコードスニペットを例として参照してください:
FAccelByteModelsV2MatchTicketOptionalParams Optionals;
Optionals.Attributes->SetStringField(TEXT("client_version"), TEXT("desired_override_string");
ApiClient->MatchmakingV2.CreateMatchTicket(MatchPool, OnStartMatchmakingSuccessDelegate, OnStartMatchmakingErrorDelegate, Optionals);
OSSの場合、以下のコードスニペットを例として参照してください:
const FString OverriddenDSVersion = UTutorialModuleOnlineUtility::GetDedicatedServerVersionOverride();
if (!OverriddenDSVersion.IsEmpty())
{
MatchmakingSearchHandle->QuerySettings.Set(SETTING_GAMESESSION_CLIENTVERSION, OverriddenDSVersion, EOnlineComparisonOp::Equals);
}
これは、セッションインターフェースのStartMatchmaking呼び出しに渡されます。ゲームでマッチメイキングを開始するために使用しているものに応じて、これらのスニペットのいずれかを使用するだけです。
上記を完了したら、ゲームのクライアントバージョンに意味のある値を使用して、そのバージョンをマッチさせたいフリート設定に同じ値をクレームキーとして追加する必要があります。client_versionに一致するフリートから取得する前に、常に専用サーバーを取得しようとする他のフリートがある場合を除き、セッションテンプレートのクレームキーは空のままにしておきます。
詳細については、高レベルの期待は、開発者(またはCIスクリプト)が1つ以上のクレームキー(クライアントバージョンに一致する文字列を含む任意のもの)でフリートを作成および設定することです。Sessionサービスが専用サーバーをリクエストすると、リクエストに順序付けられたリージョンのリストと一致するクレームキーの順序付けられたリストが含まれます。リクエストに使用するクレームキーのセットは、セッションテンプレートにリストされているクレームキーとClientVersionから構築されます。[AccelByte Multiplayer Servers(AMS)]../03-multiplayer/multiplayer-servers/index.mdx)を使用している場合、[専用サーバークレームフロー]../03-multiplayer/multiplayer-servers/10-dedicated-server-claim-flow-scenarios.md)で説明されているように、提供されたクレームキーのいずれかに一致するフリートから、提供されたリージョンのいずれかで一致する専用サーバーを見つけます。
サポートされている通知
マッチメイキングプロセスの一部として、サービスはAGS Lobbyを通じてゲームクライアントに次の通知を送信し、ログファイルで表示できます。
| 通知 | 詳細 |
|---|---|
OnSessionInvited | 保留中のセッション招待があることを示すゲームクライアントに送信される通知。 |
OnSessionJoined | セッションに正常に参加したことを示すゲームクライアントに送信される通知。 |
OnSessionKicked | セッションからキックアウトされたことを示すゲームクライアントに送信される通知。 |
OnSessionEnded | 参加していたセッションが終了したことを示すゲームクライアントに送信される通知。 |
OnSessionMembersChanged | メンバーシップに変更があったこと、プレイヤーが接続または切断されたことを通知するために、接続されているすべてのゲームクライアントに送信される通知。 |
OnSessionDataChanged | セッション情報に変更があったことを通知するために、接続されているすべてのゲームクライアントに送信される通知。 |
dsNotif | Dedicated Serverのステータスを提供するために、接続されているすべてのゲームクライアントに送信される通知。 |
OnMatchmakingTicketExpired | マッチメイキングのリクエストがMatch Poolで定義された期間を超え、タイムアウトしたことを示すゲームクライアントに送信される通知。 |
トラブルシューティング
このセクションでは、サービスを使用する際に発生する可能性のある一般的なエラーと問題、およびそれらを解決する方法に関する推奨事項を見つけることができます。
AGS LobbyからのOnMatchmakingTicketExpired通知
AGS LobbyからOnMatchmakingTicketExpired通知を受信した場合、チケットがタイムアウト制限に達し、プレイヤーがマッチメイキングから削除されたことを意味します。これは、マッチプール設定で定義されたタイムアウトが短すぎる場合、またはマッチルールセットがプレイヤーが他のプレイヤーとマッチングできるように十分なルールフレキシングを許可していない場合によく発生します。
- マッチプール設定を確認して、マッチまたはバックフィルチケットのタイムアウトが短すぎるかどうかを判断します。
- マッチルールセットを確認して、最小プレイヤーまたはチーム要件が正しく設定されているかどうかを確認します。
OnMatchmakingComplete SearchResults配列が空
マッチメイキングが完了したことを通知するマッチ結果をリスニングしているときに、Session Search HandleのSearchResults配列が空になる場合があります。これは、ハンドルがTSharedRefとして保存されていないことを意味している可能性があり、マッチメイキングセッション結果を取得できなくなります。
- Session Search Handleが全体を通して
TSharedRef型を維持していることを確認してください。