OnlineSubsystemのSession検索とDestroySessionのDelegateについて

お世話になっております。

<br/>

OnlineSubsystemプラグインのSessionインターフェイスをSteamアカウントのログインで使用しているのですが、

その際にわからない点が2点できたので質問させてください

<br/>

1.作成したSessionが、ほかのクライアントから検索できない問題の原因について

上記のCreateSessionで作成したSessionがFindSessionで検索に出てきません。

再現手順内の情報で、どこが原因かわかりますでしょうか?

テストの流れとしては、下記の感じです。

  1. EOSにSteamアカウントでログイン
  2. Session作成(作成デリゲート関数内で成功判定が返ってくる)
  3. 別のPCでログイン後検索(成功判定が返ってくるが、m_searchSessionSearch->SearchResultsがEmptyのまま)

<br/>

2.セッションをDestroyする際のDelegate関数を設定する方法

DestroySessionの際のDelegateが、直接Delegate関数をDestroy時に渡しても、

AddOnDestroySessionCompleteDelegate_Handleで渡しても呼ばれません。

確実に呼ぶ方法はありますでしょうか?

<br/>

上記2点、お手数をおかけしますがご回答いただければ幸いです。

再現手順
ロビー作成関数内

`TSharedPtr sessionSettings = MakeShareable(new FOnlineSessionSettings());
sessionSettings->bIsLANMatch = false;
sessionSettings->NumPublicConnections = 2;
sessionSettings->bAllowInvites = true;
sessionSettings->bAllowJoinInProgress = true;
sessionSettings->bAllowJoinViaPresence = true;
sessionSettings->bShouldAdvertise = true;
sessionSettings->bUsesPresence = true;
sessionSettings->bUseLobbiesIfAvailable = true;
#if defined(DEBUG)
sessionSettings->BuildUniqueId = 0; // ビルドIDが異なるとセッションが見つからないので、デバッグ環境のみ0に一致させる
#endif
sessionSettings->Set(FName(“LobbyName”), createLobbyInfo.LobbyName, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);

TSharedPtr uniqueNetId =
GetLocalUserPtrInOnlineManager()->GetPreferredUniqueNetId().GetUniqueNetId();

return sessionInterface->CreateSession(*uniqueNetId, m_sDebugSessionName, *sessionSettings);`ロビー検索関数内

`m_searchSessionSearch = MakeShareable(new FOnlineSessionSearch());

// 検索最大20件
m_searchSessionSearch->MaxSearchResults = 20;
m_searchSessionSearch->bIsLanQuery = false;

TSharedRef searchSettings = m_searchSessionSearch.ToSharedRef();

TSharedPtr uniqueNetId =
GetLocalUserPtrInOnlineManager()->GetPreferredUniqueNetId().GetUniqueNetId();

sessionInterface->FindSessions(*uniqueNetId, searchSettings);`ロビー退出関数内

`// プラグインの未実装でコンストラクタでのデリゲート関数登録が機能しないらしいので、引数で直接渡す
const FOnDestroySessionCompleteDelegate delegate =
FOnDestroySessionCompleteDelegate::CreateUObject(this, &UOnlineManager::DestroySessionCompleteDelegate);

// ホストの場合はセッション終了、その他メンバーの場合は退出するようになっているので関数を呼ぶだけ
if(!sessionInterface->DestroySession(m_sDebugSessionName, delegate)){
UE_LOG(LogApp, Error, TEXT(“Not leave lobby yet!”));
}`DefaultEngine.ini

`[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName=“GameNetDriver”,DriverClassName=“/Script/SocketSubsystemEOS.NetDriverEOS”,DriverClassNameFallback=“/Script/OnlineSubsystemUtils.IpNetDriver”)
+NetDriverDefinitions=(DefName=“DemoNetDriver”,DriverClassName=“/Script/Engine.DemoNetDriver”,DriverClassNameFallback=“/Script/Engine.DemoNetDriver”)

[OnlineSubsystem]
DefaultPlatformService=EOSPlus
NativePlatformService=Steam

[OnlineSubsystemSteam]
bEnabled=true
bUseSteamNetworking=false
bInitServerOnClient=true
SteamDevAppId=//隠し

[OnlineSubsystemEOS]
bEnabled=true

[OnlineSubsystemEOSPlus]
bEnabled=true

[/Script/OnlineSubsystemUtils.OnlineEngineInterfaceImpl]
!CompatibleUniqueNetIdTypes=ClearArray
+CompatibleUniqueNetIdTypes=EOS
+CompatibleUniqueNetIdTypes=EOSPlus
MappedUniqueNetIdTypes=((“EOSPlus”,“EOS”))

[OnlineSubsystemEOS.ExternalAuth]
+ExternalAuthServicesNames=Steam

[/Script/SocketSubsystemEOS.NetDriverEOSBase]
bIsUsingP2PSockets=true

[/Script/OnlineSubsystemEOS.EOSSettings]
CacheDir=CacheDir
DefaultArtifactName=//隠し
RTCBackgroundMode=
TickBudgetInMilliseconds=0
bEnableOverlay=True
bEnableSocialOverlay=True
bEnableEditorOverlay=False
bPreferPersistentAuth=False
TitleStorageReadChunkLength=0
+Artifacts=//隠し
-AuthScopeFlags=BasicProfile
-AuthScopeFlags=FriendsList
-AuthScopeFlags=Presence
+AuthScopeFlags=BasicProfile
+AuthScopeFlags=FriendsList
+AuthScopeFlags=Presence
bUseEAS=False
bUseEOSConnect=True
bUseEOSRTC=False
bMirrorStatsToEOS=False
bMirrorAchievementsToEOS=False
bUseEOSSessions=False
bMirrorPresenceToEAS=False
bUseNewLoginFlow=False
SteamTokenType=WebApi:epiconlineservicestest
NintendoTokenType=NintendoServiceAccount`

お世話になっております。

1 作成したSessionが他のクライアントから検索できない問題

セッションが作成には成功しているにも関わらず、FindSession()によって検索結果が空の場合​、

検索条件に SEARCH_LOBBIES = true が​指定されていないことが原因の可能性が高いです。

CreateSession時に bUseLobbiesIfAvailable = true が指定されている場合、

UnrealEngineは内部的にセッションをLobbiesAPIを使用して作成することがあります。

これにより、検索側でもLobbiesを明表的に対象にする必要があります。

検索側で FindSessions()を呼ぶ前に、以下のような設定を追加してみてください。

m_searchSessionSearch->QuerySettings.Set(SEARCH_LOBBIES, true, EOnlineComparisonOp::Equals);

関連の内容はこのページをご確認ください。

2 セッションDestroy際のDelegate問題

DestroySession()にFOnDestroySessionCompleteDelegateを直接引数として渡す方法が

内部実装により無視される場合がある可能性があります。

そのため、確実にコールバックを受け取るためには、​

​AddOnDestroySessionCompleteDelegate_Handle() を使用して事前にデリゲートを登録する方法が推奨されます。

SessionInterface->AddOnDestroySessionCompleteDelegate_Handle(FOnDestroySessionCompleteDelegate::CreateUObject(this, &ThisClass::OnDestroySessionComplete));

共有していただいたコメントでも書いておりますが、

//プラグインの未実装でコンストラクタでのデリゲート関数登録が機能しないらしいので、引数で直接渡す​もう一度initializeの段階でdelegateをbindする方法をお試しください。

よろしくお願いいたします。​

DestroySession の呼び出し自体は成功していて、セッションも正常に削除されているようですが(次回呼び出し時に null セッションの警告が出ることから)、OnDestroySessionComplete のdelegateがまったく呼ばれないという点が気になっています。

現時点での推測としては、DestroySession が内部的に即時処理されてしまっており、delegateがまだバインドされていないタイミングで完了してしまった可能性があるかと考えています。

そのため、まずはログを使って DestroySession の呼び出し前後でセッションの状態(GetNamedSession の戻り値など)や、デリゲートの登録がいつ行われているか、OnDestroySessionComplete が本当に呼ばれていないのか、あたりを追ってみるのが良さそうです。

取り急ぎタイミング周りを明確にすることで、次のステップが見えてくると思います。

DestroySessionが意図どおり動作するようになったとのことで安心しました。

bUseEOSSessions=trueの設定で、内部的にdelegate呼び出しのタイミングやルートに影響を与えてる可能性が十分ありそうです。

Destroy時、直接delegateを渡す形になったのは少し例外的かもしれませんが、

確実に動く形に落とし込めたのはとてもいい判断だったと思います。

こちらでも引き続き、同様の構成で発生しうるパターンがないか確認してみます。

また何かありましたらいつでも気軽にご相談ください。

回答ありがとうございます。​

上記1,2についてどちらも試してみたところ下記のようになりました。

Destroyに関しては引き続き関数を呼んでくれないので、もしほかに必要な情報などあれば教えてください。

(質問時に記載が漏れていましたが、UEのバージョンは​5.6です。)

作成したSessionが他のクライアントから検索できない問題

回答にあった下記を追加することで、検索に現れるようになりました。

m_searchSessionSearch->QuerySettings.Set(SEARCH_LOBBIES, true, EOnlineComparisonOp::Equals);LobbiesAPIを呼ぶように設定すると、1部のLobbyパラムも検索に含めることができるようになっているのですね

そのままJoinSessionまでできたのでご報告いたします。

2 セッションDestroy際のDelegate問題

こちらについては、修正のAddOnDestroySessionCompleteDelegate_Handleを使用したデリゲート登録でも

登録した関数を呼んでくれませんでした。​

下記のように設定したのですが、何か記載違いがありますでしょうか?

sessionInterface->AddOnDestroySessionCompleteDelegate_Handle( FOnDestroySessionCompleteDelegate::CreateUObject(this, &UOnlineManager::DestroySessionCompleteDelegate));(クラス名、関数名がプログラムに合わせて異なるだけで同じように見えます)

そのほかの情報としては、デリゲートは読んでくれませんが再度Detroyを使用とすると下記のワーニングが出るので、おそらく退出自体はできているのだと思います。

Can't destroy a null online session

​もしなにか記載を間違っていたり、他に情報が必要な場合は教えていただけますと幸いです。

回答ありがとうございます。

回答を参考にUEのLogをとってみたところ、DestroySessionを呼ぶ前後でPending->Destroyingに変化していて理想通りの動きをしていることが分かりました。

LogApp: Before DestroySession Info: Status = 2, MemberNum = 0, LogApp: After DestroySession Info: Status = 7, MemberNum = 0,そして、先ほど下記のフォーラムを参考にコードを変更したところ、デリゲートが呼ばれるようになりました。

EOS/EOSPlus OnDestroySessionCompleteDelegates がバインド関数を呼び出さない - プログラミング & スクリプティング / C++ - Epic Developer Community Forums

`IOnlineSessionPtr sessionInterface = GetOnlineSessionInterface();
if (!sessionInterface.IsValid()) {
return;
}

FOnDestroySessionCompleteDelegate delegate;
delegate.BindUObject(this, &UOnlineManager::DestroySessionCompleteDelegate);

if (!sessionInterface->DestroySession(m_sDebugSessionName, delegate)) {
UE_LOG(LogApp, Error, TEXT(“Failed to call DestroySession!”));
}`始めに質問した時と同じdelegateを直接渡す方式ですが、Sessionの通信設定の変更(bUseEOSSessionsをtrueに変更)との相性で動くようになったのかもしれません。

Destroyの時だけ特殊な記法とはなってしまいますが、理想通り動くようになったので

今回はこの修正で完了としようと思います。

ご回答いただきありがとうございました。