専用サーバーの実行環境に外部サーバーサービス(GameLift、PlayFab等)を使用する場合のOnlineSubsystemに関する設定につきまして

いつも大変お世話になっております。

現在、外部クラウドサーバーサービス上にて専用サーバーを実行する、

マルチプレイかつマルチプラットフォームに対応するアプリケーションの研究を行っております。

各コンシューマープラットフォームと統合する前に、まずはSteamとの統合を検証しようと

https://dev.epicgames.com/documentation/ja-jp/unreal-engine/online-subsystem-steam-interface-in-unreal-engineを参照しながら

DefaultEngine.iniに「[OnlineSubsystem] DefaultPlatformService=Steam」の記述を行ったところ、

クライアントから専用サーバーへの接続が上手くいかなくなってしまいまして、サーバーアプリケーションとクライアントアプリケーションそれぞれに行うべき

OnlineSubsystemの設定について不明瞭な点がありましたので確認させていただきたく思います。

使用しておりますエンジンのバージョンは5.5.3です。また現状では外部サーバーサービスに対してHTTPSにてリクエストを送り、

そのレスポンスとして返ってきたサーバーのipアドレスを「UGameplayStatics::OpenLevel」にて直接指定して遷移することでマルチプレイを行っております。

先んじて2点、前提の認識の確認をさせていただきたく思います。

1)まず、DefaultEngine.iniにて「DefaultPlatformService」の指定を行わなかった場合、

「OnlineSubsystemNull」モジュールが使われるようになるという認識です。このOnlineSubsystemNullは製品として使用することは非推奨であり、

開発におけるモックやカスタマイズ元としての用途を想定して作成されているという理解でよろしいでしょうか?

2)そもそもOnlineSubsystemにプラットフォームの指定を行うということは、Engine側で行うオンラインセッションに関する処理やユーザー名の取得、

プラットフォームの各機能(実績や招待など)が、指定した各プラットフォームのAPIを使うようになるという理解であっておりますでしょうか?

そのうえで、重ねてお手数ではございますが、以下につきましてご確認願えますでしょうか。

3)コミュニティの別の投稿を確認していたところ、そもそも外部サーバーサービスを使う時点で

OnlineSubsystemにプラットフォーム固有のものを入れるわけにはいかないため、EOSや独自にカスタマイズしたOnlineSubsystemを使うべきという投稿を見かけました。

[Content removed]

その内容が正しいのであれば、例えばEOSを使うとした場合にはDefaultEngine.iniに「DefaultPlatformService=EOS」と記述することになるのかと思いますが、

この「DefaultPlatformService=EOS」はクライアントにも適用されるという認識で良いのでしょうか?

その状態で、Steamをはじめとする各プラットフォームの機能(ユーザー名の取得や実績、招待など)が使えるのでしょうか?

4)こちらもコミュニティの投稿で、「サーバーとクライアントのOnlineSubsystemは揃えるべき」という投稿を見かけましたが、

こちらの認識はあっておりますでしょうか?(申し訳ありません、URLを失念しました)

その内容が正しいのであれば、3の質問と似た話になりますが、例えばSteamの実績機能等を使うために

クライアントは「DefaultPlatformService=Steam」を指定しなければならないが、

同時にサーバーアプリケーション側にも「DefaultPlatformService=Steam」が適用されるという認識です。

5)サーバー・クライアントアプリケーションや、プラットフォームごとに「DefaultEngine.ini」をファイルごと分割し、

適用されるパラメータを変更することが可能なのでしょうか?

6)※こちらはAWSとSteamに関連する質問になるため、もし分かればで結構です。

現在AWSのGameLift-AnywhereFleetを利用し、手元の1台のPCにて検証を進めております。

しかしながらUE用の専用サーバーとクライアントアプリケーションを同一マシン上で稼働させることは不可能という認識でよろしいでしょうか?

(こちらのredditの投稿では回避策は無いとコメントされておりますが、正しいのでしょうか?https://www.reddit.com/r/unrealengine/comments/dwa6fz/how_to_test_dedicated_server_and_client_with/

以上となります。

最終的な目標としましては冒頭にも記載の通り外部クラウドサービス上で専用サーバーを起動し、

多種のプラットフォームでリリースしたアプリケーションから相互に自由なマッチングが可能となる状態を目指しておりますが、

UEを利用したマルチプレイ実装の経験が浅く見当違いな質問をしているかもしれません。

そもそも手法として誤っているのであればご指摘いただけると大変助かります。

またこのような構成を行っている作品は既に多数存在する認識ですが、ベストプラクティスをご教示いただけますと大変参考になります。

お手数ではございますが何卒宜しくお願い致します。

> 1)まず、DefaultEngine.iniにて「DefaultPlatformService」の指定を行わなかった場合、

いいえ。OnlineSubsystemNullはほとんどのインターフェイスを含まないベースの実装です。(OnlineSubsystemNull.cppを参照してみてください)

独自のゲームサーバーを構成していてIp接続で通信が確立できれば十分なケースでは製品にも利用できます。

> 2)そもそもOnlineSubsystemにプラットフォームの指定を行うということは、Engine側で行うオンラインセッションに関する処理やユーザー名の取得、

はい。基本的にはその認識で間違いありません。オンラインサブシステムは複数同時に利用できるので特定の用途では別のオンラインサブシステムのインターフェイスを利用することも出来ます。以下の記事もご参照ください。

https://qiita.com/EGJ-Ken_Kuwano/items/693e125b2111fdffc1da

> 3)コミュニティの別の投稿を確認していたところ、そもそも外部サーバーサービスを使う時点で

デディケートサーバー上ではクライアントと同じように各プラットフォームのサービスを利用することはできません。

そのためサーバー上で利用できるオンラインサブシステムを利用するという認識は正しいです。

必要なインターフェイスを振り分けて利用するような独自のオンラインサブシステムを作成することも一般的な構成です。

また2の回答にあるように複数のオンラインサブシステムを同時に利用することは問題ありません。

もしデディケートサーバーとクライアントでDefaultPlatformServiceを切り替えたほうが運用上好ましいようであれば、デディケートサーバーのみに適用されるDedicatedServerEngine.iniに設定を記述することも可能です。

> 4)こちらもコミュニティの投稿で、「サーバーとクライアントのOnlineSubsystemは揃えるべき」という投稿を見かけましたが、

文脈を早くできていないので確実なことは申し上げられませんがListenServerを利用する場合はそろえるべきかと思います。

また各プラットフォーム毎の専用コードがタイトル側のコードに散在することになるとあまり運用上好ましいものではないので、独自のサブシステムを作成してプラットフォームの差を吸収することも検討できます。

> 5)サーバー・クライアントアプリケーションや、プラットフォームごとに「DefaultEngine.ini」をファイルごと分割し、

はい。4)でも回答さしあげましたが、デディケートサーバーが動作するプラットフォーム共通の設定であればDedicatedServerEngine.iniが利用できます。

> 6)※こちらはAWSとSteamに関連する質問になるため、もし分かればで結構です。

こちらはSteamのAPIが1PC上で複数インスタンスの起動を許可していないことによる制限だと思われます。

Steamのネットワーキング機能などのサービス(リレー接続など)について吟味頂いて、

デディケートサーバー側では無効化できるのであれば-nosteamオプションなどを検討いただけると思います。

ご確認ありがとうございます。ご教授いただいたOnlineSubsystemを指定して使い分ける手法についても確認いたしました。

しかしながら大変お手数ではございますが、追加で確認させてください。

ご教授いただいた手法では、「IOnlineSubsystem::Get()」を呼び出す際に各プラットフォーム名の引数を指定して与えることで

任意の箇所で機能ごとに使用するOnlineSubsystemを切り替えることが可能とのことですが、最初のご質問にも記載しました通り

現状は外部サーバーサービスのipアドレスを、「UGameplayStatics::OpenLevel」にて直接指定してレベルに遷移することでマルチプレイを行っております。

そのため、「IOnlineSubsystem::GetSessionInterface」などは使用しておらず、

OnlineSessionInterfaceを介したCreateSessionやJoinSession等の機能については未使用の状態となっております。

つまりIp接続のみで通信を確立している状態でございますため、専用サーバー、クライアントともに

DefaultPlatformService=Null」と指定すべき状態かと理解しております。

しかしながらそうしますとクライアント側ではSteamAPIの初期化である「SteamAPI_Init」が実行されないためか、Steamオーバーレイの表示が出来ずプラットフォームの機能が使えません。

専用サーバーが「DefaultPlatformService=Null」、かつ、クライアント側が「DefaultPlatformService=Steam」の状態での接続も検証してみましたが、

その場合には専用サーバーへの接続時、クライアント側にて以下のようなエラーが発生し専用サーバーで起動しているレベルへ遷移することが出来ない状態です。

>LogSockets: Warning: Tried to bind address with protocol STEAM to a socket with protocol IPv4

>LogNet: Warning: Could not create socket for bind address 76561199670773266, got error SteamSockets: binding to port 0 failed (0)

>LogNet: Warning: Encountered an error while creating sockets for the bind addresses.

>LogNet: Error: InitBindSockets failed:

また上記検証に加え、クライアント側の「[OnlineSubsystemSteam]bUseSteamNetworking=false」とすることで

OpenLevelで呼び出されるエンジン内のネットワーク通信部分にSteamのAPIを使わないようにできるのかと思い試してみましたが、

その場合でもクライアントの接続時に、専用サーバー側で「LogNet: PreLogin failure: incompatible_unique_net_id」というエラーが発生し、接続を行うことが出来ない状態です。

どのように記述すればSteamオーバーレイが呼び出せる状態、かつ、IP接続での通信が可能となるのでしょうか?

そもそも設計が誤っているのか、UGameplayStatics::OpenLevelではこのようなケースへの対応は不可能なのか等、判断がつかないためご教授願えますでしょうか。

また、(5)の回答につきましてですが、いただいた情報と以下のページを参考にコンフィグファイルの分割について確認しております。

https://dev.epicgames.com/documentation/ja-jp/unreal-engine/configuration-files-in-unreal-engine

しかしながら「DedicatedServerEngine.ini」という名前は上記ページの[コンフィギュレーション ファイルの階層]の構成には一致しないように思えるのですが、

<プロジェクトディレクトリ>/Config/DedicatedServerEngine.iniと配置すれば、専用サーバー用のコンフィグとしてオーバーライドされ動作するという理解で良いのでしょうか?

以上2点、重ねてお手数をおかけしますがご確認いただけますでしょうか。

また私事で大変申し訳ございませんが、近日中に1週間程度出張で不在となってしまいご返信が遅れてしまうかもしれません。

何卒ご容赦ください。

> その場合でもクライアントの接続時に、専用サーバー側で「LogNet: PreLogin failure: incompatible_unique_net_id」というエラーが発生し、接続を行うことが出来ない状態です。

サーバーで動作しているゲームモードがデフォルトのPreLogin関数でクライアントのFUniqueNetIdReplを判定してエラーになっています。

デフォルトのPreLoginは同じOSSを用いていることが前提となっているので、様々なクライアントプラットフォームを受け付けるサーバーではPreLoginをオーバーライドし受け取ったIDやオプションなどから独自にログインの可否を判定する実装を追加する必要があります。

> <プロジェクトディレクトリ>/Config/DedicatedServerEngine.iniと配置すれば、専用サーバー用のコンフィグとしてオーバーライドされ動作するという理解で良いのでしょうか?

はい。その通りです。

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

ご返答遅れまして申し訳ございません。迅速なご回答ありがとうございます。

ご教授いただいた通り、クライアント側を「bUseSteamNetworking=false」に設定した上で、

AGameModeBase::PreLoginに実装されておりました「bUniqueIdCheckOk」に関する処理をスキップするようにし、

UniqueIdが一致していなくても「GameSession::ApproveLogin」を呼び出すようにしましたところ

当初の目的通りSteamの初期化を行った上で外部専用サーバーへ接続することが可能になりました。誠にありがとうございます。

最後に重ねての質問となってしまい恐縮ですが、

サーバーとクライアントで異なるOnlineSubsystemを使うことによってUniqueIdが異なるようになるとのことですが、

UniqueIdが異なる実装となることで、他の箇所で留意すべき点などございますでしょうか?

懸念点等ございましたらご教授いただければ幸いです。

また「DedicatedServerEngine.ini」につきましても、

ご教授いただいた通りに配置を行うことで専用サーバー側を「DefaultPlatformService=Null」、クライアント側を「DefaultPlatformService=Steam」と、

無事に使い分けが適用されるようになりました。誠にありがとうございました。

> サーバーとクライアントで異なるOnlineSubsystemを使うことによってUniqueIdが異なるようになるとのことですが、

> UniqueIdが異なる実装となることで、他の箇所で留意すべき点などございますでしょうか?

現状ではPreloginで無制限にクライアントを受け入れている状態だと思います。マッチング後にゲームが成立しなかった場合などで意図せずマッチングの対象外のプレイヤーがログインを試みるケースなど、そのプレイヤーのログインを受け入れるべきかどうかタイトルに合わせてPreloginの実装を加える必要がございます。その際にはUniqueIdやなんらかのトークンを使って判定を行うことになります。​

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

ご返答遅れまして申し訳ございません。

この度はご丁寧な解説をいただき、誠にありがとうございます。

本手法によってPreloginでのユーザー受け入れについて自前で考慮しなければならなくなる点、承知いたしました。

今後必要に応じて実装を見直しつつ進行したいと思います。

おかげさまで懸念事項が解消されました。本件クローズしていただいて問題ございません。

引き続き、よろしくお願いいたします。