注釈:本資料はAI技術を用いて翻訳されています。
OSSを使用したマッチメイキングの設定
ゲームにマッチメイキングを実装するには、以下の手順に従ってください。
前提条件
-
DefaultEngine.iniファイルに以下を追加して、AccelByte Online Subsystem (OSS)でSessions V2を有効にします。[OnlineSubsystemAccelByte]
bEnableV2Sessions=true -
DefaultEngine.iniに以下を追加して、AccelByteNetworkUtilitiesを有効にします。[AccelByteNetworkUtilities]
UseTurnManager=true
HostCheckTimeout=5
[/Script/AccelByteNetworkUtilities.IpNetDriverAccelByte]
NetConnectionClassName=AccelByteNetworkUtilities.IpConnectionAccelByte
AllowDownloads=false
[/Script/Engine.Engine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/AccelByteNetworkUtilities.IpNetDriverAccelByte",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
+NetDriverDefinitions=(DefName="DemoNetDriver",DriverClassName="/Script/Engine.DemoNetDriver",DriverClassNameFallback="/Script/Engine.DemoNetDriver") -
Admin Portalで、Game ClientにMatchmakingとSession V2の必要な権限を追加します。
-
Game ClientはAccelByteバックエンドで認証され、Lobbyサービスに接続されている必要があります。
Non-seamless Travel失敗の回避策
Non-Seamless Travelの際、Unreal Engineの基本ネットワーククラス(UIpConnection)は、AccelByte IPフォーマットに対してDNS解決を試みますが、このフォーマットは有効なDNSホスト名ではありません。その結果、解決が失敗し、ネットワークエラーが発生します。
この問題を回避するには、DefaultEngine.iniファイルの[AccelByteNetworkUtilities]セクションでbNonSeamlessTravelUseNewConnection=trueを設定します。このオプションを有効にすると、基本接続の初期化前にDisableAddressResolution()が呼び出され、Unreal EngineがAccelByteアドレスに対してDNS解決を試みることを防ぎます。
例:
...
[AccelByteNetworkUtilities]
bNonSeamlessTravelUseNewConnection=true
...
マッチメイキングの開始
マッチメイキングを開始する予定の関数内で、AccelByte OSSからSession Interfaceを取得する必要があります。マッチメイキングをリクエストするために使用する、FOnlineSessionAccelBytePtr型のカスタムAccelByte 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;
}
Game Clientの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: 指定されたゲームモードの前提条件の一部として定義したマッチプールの名前。これにより、Matchmakingサービスは新しく作成されたマッチチケットをそのマッチプールに追加して評価します。
- Comparison Operator: セッション検索の一部として使用されるOSSオペレータ。この場合は
EOnlineComparisonOp::Equalsです。
マッチ結果をリッスンするために、FOnMatchmakingCompleteDelegateコールバックデリゲートを登録する必要があります。これは、マッチメイキングが完了したときにトリガーされます。サンプルコードについては、サンプルコールバック関数セクションを参照してください。
- Session Name: マッチが成功した場合に作成されるゲームセッションの名前。
- Success Value: マッチメイキングがマッチを正常に見つけたかどうかを示すブール値。
// 戻り値の型がvoidで、以下のパラメータを持つ関数をバインドします:
// FName SessionName, bool bWasSuccessful
const FOnMatchmakingCompleteDelegate OnMatchmakingCompleteDelegate = /* ラムダまたはクラスメソッドにバインド */;
SessionInterface->AddOnMatchmakingCompleteDelegate_Handle(OnMatchmakingCompleteDelegate);
上記の準備ができたら、Session InterfaceからStartMatchmaking()を呼び出して、マッチメイキングの開始をリクエストできます。この関数は以下のパラメータを取ります。
-
Player Controller ID: マッチメイキング中にMatch Ticketが送信されるプレイヤーのOSS ID。
-
Session Name: マッチメイキングが成功した場合に作成されるセッションの名前。通常、
NAME_GameSessionを渡します。 -
Session Settings: Sessionサービスがゲームセッションを作成する際に使用するセッション設定、
FOnlineSessionSettings()。この場合、空のオブジェクトを渡すことで、Sessionサービスに設定を割り当てさせます。 -
Session Search Handle: マッチメイキングが成功した場合に作成されるゲームセッションを保存するために、このセクションの前半で作成したSession Search Handle。
StartMatchmaking()へのリクエストが行われ、呼び出しがtrueを返すと仮定すると、このセクションの前半で定義したSession Search Handleを、将来のアクセスのためにクラスメンバーにバインドする必要があります。StartMatchmaking()がfalseを返す場合、Matchmakingサービスへの呼び出しに問題があったことを示します。
if (SessionInterface->StartMatchmaking(USER_ID_TO_MATCHMAKING_USER_ARRAY(LocalPlayerId.ToSharedRef()), NAME_GameSession, FOnlineSessionSettings(), MatchmakingSearchHandle, OnStartMatchmakingCompleteDelegate))
{
// 現在の検索結果ハンドルクラスメンバーを、マッチメイキングサービスに渡された検索ハンドルで更新します。
CurrentMatchmakingSearchHandle = MatchmakingSearchHandle;
}
Turn Server QoSを使用したマッチメイキングの開始
この機能はAGSバージョン3.75以降でのみ利用可能です。
この実装は、マッチチケットを作成する前にTurn Server QoSを取得し、レイテンシ情報を提供する低レベルのタスクを自動的に処理します。
SetIsP2PMatchmakingのカスタム関数にアクセスするには、まずFOnlineSessionSearchAccelByteクラスを使用して新しいマッチメイキング検索ハンドルを指定します。次に、パラメータをtrueに設定して、マッチがP2Pセッション用であることを示します。最後に、マッチメイキング検索ハンドルをStartMatchmaking関数に渡してマッチを開始します。
TSharedRef<FOnlineSessionSearchAccelByte> MatchmakingSearchHandle = MakeShared<FOnlineSessionSearchAccelByte>();
MatchmakingSearchHandle->QuerySettings.Set(SETTING_SESSION_MATCHPOOL, MatchPoolName, EOnlineComparisonOp::Equals);
MatchmakingSearchHandle->SetIsP2PMatchmaking(true);
if (SessionInterface_User1->StartMatchmaking(USER_ID_TO_MATCHMAKING_USER_ARRAY(LocalUserId1.ToSharedRef()), NAME_GameSession, FOnlineSessionSettings(), MatchmakingSearchHandle, OnStartMatchmakingCompleteDelegate))
{
CurrentMatchmakingSearchHandle = MatchmakingSearchHandle;
}
ゲームセッションへの参加とP2P接続を使用した移動
マッチメイキングが完了すると、マッチメイキング開始前にバインドした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コールバックデリゲートを登録します。これは、参加リクエストが完了したときにトリガーされます。このデリゲートでは、P2P接続も処理する必要があります。ユーザーがゲームセッションリーダーかどうかを確認する必要があります。ユーザーがゲームセッションリーダー(ゲームセッションに最初に参加したユーザー)の場合、このユーザーをリッスンサーバーとして設定する必要があります。ユーザーが通常のメンバーの場合、ゲームセッションリーダーへの接続を開始する必要があります。
// 指定されたセッションへの参加のためのデリゲートを登録します
const FOnJoinSessionCompleteDelegate OnJoinSessionCompleteDelegate = FOnJoinSessionCompleteDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnJoinSessionComplete);
JoinSessionDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegate);
以下は、P2P接続を処理するためのOnJoinSessionCompleteDelegateのサンプルです。
void UOSSDemoGameSessionSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
// ゲームセッション以外の参加結果を無視します
if (SessionName != NAME_GameSession)
{
return;
}
if (Result != EOnJoinSessionCompleteResult::Success)
{
return;
}
const FOnlineSessionAccelBytePtr SessionInterface = GetSessionInterface();
ensure(SessionInterface.IsValid());
FNamedOnlineSession* Session = SessionInterface->GetNamedSession(SessionName);
if (!ensure(Session != nullptr))
{
return;
}
TSharedPtr<FOnlineSessionInfoAccelByteV2> SessionInfo = StaticCastSharedPtr<FOnlineSessionInfoAccelByteV2>(Session->SessionInfo);
if (!ensure(SessionInfo.IsValid()))
{
return;
}
ULocalPlayer* LocalPlayer = GetLocalPlayer();
if (!ensure(LocalPlayer != nullptr))
{
return;
}
APlayerController* Controller = LocalPlayer->GetPlayerController(GetWorld());
if (!ensure(Controller != nullptr))
{
return;
}
// 作成されたセッションのサーバータイプがNONE(ローカル)の場合、接続情報はセッション属性にあります
const EAccelByteV2SessionConfigurationServerType ServerType = SessionInfo->GetServerType();
if (ServerType != EAccelByteV2SessionConfigurationServerType::P2P)
{
// これはP2Pセッションではありません
return;
}
FString TravelUrl{};
if (SessionInterface->GetResolvedConnectString(SessionName, TravelUrl, NAME_GamePort) && !TravelUrl.IsEmpty())
{
if(SessionInterface->IsPlayerP2PHost(LocalPlayerId, SessionName))
{
// リッスンサーバーとして移動します
FString MapName;
Session->SessionSettings.Get(SETTING_MAPNAME, MapName);
Controller->ClientTravel(FString::Printf(TEXT("%s?listen"), *MapName), TRAVEL_Absolute);
}
else
{
Controller->ClientTravel(TravelUrl, TRAVEL_Absolute);
}
}
}
上記の準備ができたら、Session InterfaceからJoinSession()を呼び出して、返されたセッションに参加できます。この関数は以下のパラメータを取ります。
-
Player Controller ID: マッチメイキング中にマッチチケットが送信されるプレイヤーのOSS ID。
-
Session Name: マッチメイキングが成功した場合に作成されるゲームセッションの名前。
-
Session: Sessionサービスが後でアクセスするためにゲームセッション情報を割り当てるOSS Sessionオブジェクト。
SessionInterface->JoinSession(LocalPlayerId.ToSharedRef().Get(), NAME_GameSession, Session);
サンプルコールバック関数
以下は、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;
}
// 続行する前に、配列に有効なセッション検索結果があることを確認します
if (!CurrentMatchmakingSearchHandle->SearchResults.IsValidIndex(0))
{
return false;
}
FOnlineSessionSearchResult MatchResult = CurrentMatchmakingSearchHandle->SearchResults[0];
// 既に参加しているゲームセッションがある場合は、このセッションに参加するために破棄します
if (SessionInterface->GetNamedSession(NAME_GameSession) != nullptr)
{
const FOnDestroySessionCompleteDelegate OnDestroySessionForJoinCompleteDelegate = FOnDestroySessionCompleteDelegate::CreateUObject(this, &UOSSDemoGameSessionSubsystem::OnDestroySessionForJoinComplete, Session);
return SessionInterface->DestroySession(NAME_GameSession, OnDestroySessionForJoinCompleteDelegate);
}
// 指定されたセッションへの参加のためのデリゲートを登録します
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);
}
デバッグ目的で、ゲーム起動時に追加パラメータ-iceforcerelayを渡すことで、Interactive Connectivity Establishment (ICE)接続として**Relay (TURN)**を使用できます。