P2P をセッションブラウザ (非推奨) に統合する
注釈:本資料はAI技術を用いて翻訳されています。
セッションブラウザは非推奨となり、ゲームセッションに置き換えられました。詳細については、ゲームセッションを使用したピアツーピア (P2P)を参照してください。
概要
この記事では、AccelByte Gaming Services (AGS) Online Subsystem (OSS) for Unreal Engine を使用して、ピアツーピアセッションのホスティング、参加、ブラウジングの基本について説明します。これにより、ゲームクライアントは専用サーバーを必要とせずに接続して一緒にプレイできます。さらに、セッションブラウザの実装により、プレイヤーはホストプレイヤーを知らなくても、既存のオープンなピアツーピア (P2P) セッションを見つけて参加できます。
前提条件
このガイドの手順を完了するには、以下が必要です。
- OSS の使用を含む Unreal Engine の知識。
- プロジェクトにインストールされた AGS Game SDK、NetworkUtilities、および OnlineSubsystem プラグイン。
- AGS Admin Portal へのアクセスと、ゲーム用の名前空間。
- タイプが P2P に設定され、参加可能性が OPEN に設定されたセッションテンプレート。
プラグインの設定
P2P セッションブラウザ統合のためにプラグインを準備するには、次の手順に従います。
-
DefaultEngine.iniファイルで V2 セッションを有効にします。[OnlineSubsystemAccelByte]
bEnableV2Sessions=true -
Turn サーバーとネットドライバーを設定します。
[AccelByteNetworkUtilities]
UseTurnManager=true
TurnServerSecret=<your-turn-secret>
[/Script/AccelByteNetworkUtilities.IpNetDriverAccelByte]
NetConnectionClassName=AccelByteNetworkUtilities.IpConnectionAccelByte -
プラットフォームごとにネットドライバー定義を設定します。たとえば、Windows の場合は、
WindowsEngine.iniに以下を追加します。[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/AccelByteNetworkUtilities.IpNetDriverAccelByte",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
+NetDriverDefinitions=(DefName="DemoNetDriver",DriverClassName="/Script/Engine.DemoNetDriver",DriverClassNameFallback="/Script/Engine.DemoNetDriver")
P2P セッションのホスト
以下は、セッションテンプレートを使用してセッションを作成する例です。最初にいくつかのセットアップを行い、次に OSS セッションインターフェースでCreateSessionを呼び出します。
-
AGS Session インターフェースを取得します。
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
if (!ensure(Subsystem != nullptr))
{
return;
}
FOnlineSessionV2AccelBytePtr SessionInterface;
if (!FOnlineSessionV2AccelByte::GetFromSubsystem(Subsystem, SessionInterface))
{
return;
} -
セッション設定を構成します。
FOnlineSessionSettings NewSessionSettings;
// This would be the name of the session template created in the Admin Portal
NewSessionSettings.Set(SETTING_SESSION_TEMPLATE_NAME, TEXT("P2PSession"));
// You want the new session to be a game session, as opposed to a party session
NewSessionSettings.Set(SETTING_SESSION_TYPE, SETTING_SESSION_TYPE_GAME_SESSION);
// You need some kind of parameter that the session browser can later use
// to query for sessions
NewSessionSettings.Set(FName(TEXT("IS_P2P_SESSION")), TEXT("true"));
// At this point, any other custom settings can be applied. For example, you
// can add a map name that you'll later use when you're hosting the P2P session
NewSessionSettings.Set(SETTING_MAPNAME, TEXT("MapName")); -
実際にセッションを作成する呼び出しを行います。
// You create a delegate which will be triggered when the session creation is
// complete, inside of which you'll call StartSession and perform a travel
const FOnCreateSessionCompleteDelegate OnCreateSessionCompleteDelegate =
FOnCreateSessionCompleteDelegate::CreateUObject(this,
&MyClass::OnCreateSessionComplete);
FDelegateHandle CreateSessionDelegateHandle =
SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(
OnCreateSessionCompleteDelegate);
// PlayerId is an FUniqueNetIdPtr for the player
SessionInterface->CreateSession(
PlayerId.ToSharedRef().Get(), NAME_GameSession, NewSessionSettings);上記のコードでは、セッション作成完了デリゲートのハンドラーが追加されています。
-
ステップ 3 で追加されたハンドラー内で、以下を実行します。
-
SessionNameデリゲートパラメータを使用して、これが正しいセッションであることを確認します。if(SessionName != NAME_GameSession)
{
return;
}ヒントセッション名をパラメータとして受け取るデリゲートハンドラーについては、必ず上記を確認してください。
-
セッションインターフェースを再度取得します。その後、実際のセッションインスタンスを取得し、セッションを開始済みとしてマークできます。
FNamedOnlineSession* Session = SessionInterface->GetNamedSession(SessionName);
if (!ensure(Session != nullptr))
{
return;
}
SessionInterface->StartSession(SessionName); -
トラベル URL を構築してトラベルを実行します。
// You'll use the previously-set map name for traveling
FString MapName;
Session->SessionSettings.Get(SETTING_MAPNAME, MapName);
// Constructing the travel URL with "?listen" appended to the map name so that you host a listen server
const FString TravelUrl = FString::Printf(TEXT("%s?listen"), *MapName);
// PlayerController is a pointer to an APlayerController for the local player
Controller->ClientTravel(TravelUrl, TRAVEL_Absolute);ヒント一般的に、マップの読み込み後に設定される値を示すセッション設定を追加して、セッションが他のプレイヤーの参加準備ができているかどうかを示すと便利です。
-
P2P セッションのブラウジングと参加
P2P セッションをブラウジングするには、前のステップのIS_P2P_SESSION設定を使用して、Session インターフェースのFindSessionsメソッドを使用します。まず、AGS Session インターフェースを再度取得する必要があります。次に、クエリしたい属性を設定します。
TSharedPtr<FOnlineSessionSearch> QuerySessionsHandle =
MakeShared<FOnlineSessionSearch>();
// You'll set the maximum search results to some arbitrary value
QuerySessionsHandle->MaxSearchResults = 100;
// Search for sessions with the P2P setting you used earlier
QuerySessionsHandle->QuerySettings.Set(
FName(TEXT("IS_P2P_SESSION")), TEXT("true"));
// You can also query for other session settings, such as MAPNAME
QuerySessionsHandle->QuerySettings.Set(SETTING_MAPNAME, TEXT("MapName"));
検索結果が含まれるため、FOnlineSessionSearchハンドルをFindSessions完了デリゲートで使用するために保持しておく必要があります。
次に、FindSessionsの呼び出しを行います。
const FOnFindSessionsCompleteDelegate OnFindSessionsCompleteDelegate =
FOnFindSessionsCompleteDelegate::CreateUObject(
this, &MyClass::OnFindSessionsComplete);
FDelegateHandle FindSessionsCompleteDelegateHandle =
SessionInterface->AddOnFindSessionsCompleteDelegate_Handle(
OnFindSessionsCompleteDelegate);
// PlayerId is an FUniqueNetIdPtr for the player
SessionInterface->FindSessions(
PlayerId.ToSharedRef().Get(), QuerySessionsHandle.ToSharedRef());
OnFindSessionsCompleteデリゲートのハンドラー内では、FOnlineSessionSearchResultの配列にアクセスでき、これをセッションブラウザ UI でセッションのリストを表示するために使用できます。たとえば、ハンドラーはこの配列を別のデリゲートに渡してから、検索ハンドルをリセットすることがよくあります。
SomeSessionBrowserListingDelegate.Broadcast(QuerySessionsHandle->SearchResults);
QuerySessionsHandle.Reset();
これらのセッションのいずれかに参加するには、クライアントは上記の配列からセッション検索結果の 1 つを渡してJoinSessionメソッドを呼び出すだけです。最初に Session インターフェースを再度取得し、次に参加を実行します。
const FOnJoinSessionCompleteDelegate OnJoinSessionCompleteDelegate =
FOnJoinSessionCompleteDelegate::CreateUObject(
this, &MyClass::OnJoinSessionComplete);
FDelegateHandle JoinSessionDelegateHandle =
SessionInterface->AddOnJoinSessionCompleteDelegate_Handle(
OnJoinSessionCompleteDelegate);
// PlayerId is an FUniqueNetIdPtr for the player, and Session is simply an instance of FOnlineSessionSearchResult
return SessionInterface->JoinSession(
PlayerId.ToSharedRef().Get(), NAME_GameSession, Session);
参加する前に、GetNamedSessionを使用してプレイヤーが既にセッションに参加しているかどうかを確認することをお勧めします。参加している場合は、DestroySessionを呼び出し、そのメソッドのデリゲートがトリガーされたらセッションに参加します。
JoinSessionCompleteデリゲートハンドラー内で、トラベルを実行します。繰り返しますが、Session インターフェースを取得してから、トラベル URL を取得してクライアントトラベルを実行します。
FString TravelUrl{};
// SessionName is a parameter from the join delegate
if (SessionInterface->GetResolvedConnectString(SessionName, TravelUrl,
NAME_GamePort) && !TravelUrl.IsEmpty())
{
// PlayerController is a pointer to an APlayerController for the local player
PlayerController->ClientTravel(TravelUrl, TRAVEL_Absolute);
}
P2P セッションの場合、トラベル URL はaccelbyte.<host_user_id>:<port>の形式になります。この場合、解決された接続文字列を取得する呼び出しは、ローカルセッション情報からトラベル URL を単に生成しているだけです。
トラブルシューティング
このセクションでは、このサービスを使用する際に発生する可能性のある一般的なエラーと問題、およびそれらを解決する方法に関する推奨事項を見つけることができます。
プレイヤーの早すぎる参加
参加プレイヤー (ホスト以外) がマップが読み込まれる前にサーバーへのトラベルを試みる問題が発生する可能性があります。
提案
この解決策は、セッション設定 (例:SETTING_JOIN_READY) を追加することです。これはFCoreUObjectDelegates::PostLoadMapWithWorldに追加されたデリゲート内で"true"のような値に設定されます。
FOnlineSessionSettings* SessionSettings =
SessionInterface->GetSessionSettings(NAME_GameSession);
SessionSettings->Set(FName(TEXT("JOIN_READY")), TEXT("true"));
SessionInterface->UpdateSession(NAME_GameSession, *SessionSettings);
次に、参加側では、セッションインターフェースのUpdateReceivedデリゲートをリッスンし、参加を試みる前にそのセッション設定を探します。また、セッションブラウザのFindSessionsの使用でこのパラメータをクエリ設定に追加して、参加準備ができているセッションのみをブラウザに表示することも役立ちます。