Blog ブログ

UE4でネットワーク機能実装中に「OnPostLogin イベントが呼び出されない!!」

皆様、こんにちは!
4月に入社し、もう半年も経ちました!
エンジニアの山口です。

さて、今回はUE4のネットワーク機能を使う機会があったのでその際に、
詰まったところとその解決策を紹介しようと思います。

詰まったところと言うと、タイトルにもある通りUE4での通信を実装する際に、ホストにゲストが
接続する処理がありますが、そこでホスト側でコールバックとして呼ばれるOnPostLogin
というものが呼び出されない問題です。
また、少しではありますが、Online SubsystemのSessionについて調べたことを記載しています。

今回、UE4のネットワーク機能でOnline Subsystemというものを使いました。
Online SubsystemとはUE4が提供しているマルチプラットフォームに対応しているオンライン機能です。
しかし、マルチプラットフォーム対応と書いてありますが、公式サイトには
「全てのプラットフォームのインターフェースを実装しているとは限らない」
と記載されていますので注意が必要です。

以前UE4のネットワーク機能を少しだけ触ったことがあるのですが、
ゲストはOpenLevelノードを使いホストに接続していた記憶があります。
このOnline SubsystemのSession機能を初めて使いましたが、
OpenLevelでホストに接続を自分で行わなくてもよくなっていて、簡単になったなと感じました。
Online SubsystemのSession機能は何をしてくれるのかと言うとマッチメイキングをしてくれる機能です。

さて、これから紹介する問題が起きた前提として、
・ローカルネットワーク内で行っている
・PCは2台用意してテストを行っている
・ホストとゲストは一人ずつとする
・Online Subsystem Steamを使用している
上記を前提のもと書きます。

OnPostLogin イベントが呼び出されない
OnPostLoginというのはホストがゲストに接続した時にホスト側で、
ゲストが正常に接続した時に呼ばれるものです。

ホストでOnPostLoginが呼び出されるのは
1.ホストのワールドへゲストが接続
2.ログインしてホストがゲストのPlayerControllerを正常に生成
上記の順番に処理された場合に呼び出されるようになっています。
今回は2の処理でPlayerControllerが正常に生成されておらず、
Login処理でPlayerControllerを生成し、戻り値としているところが
return nullptrとなり、その後の判定でLogin Failedとなっていました。

Login Failedとなっては、失敗しているわけですから、当然OnPostLogin(ログイン後の処理)は
呼び出されるはずが無いですね……

・そもそもOnPostLoginを呼び出すためには何をしているの?
エンジンコードではPostLoginという関数でホスト側で処理されています。
PostLoginはその名の通りログインの後という意味です。
PostがあるということはPreLoginもあります。
UE4のホストへの接続処理の流れとしては
PreLogin → Login → PostLogin となっています。

PreLoginではユーザの受け入れの可否を判定される処理となっています。

LoginではPlayerControllerを生成し、UE4のGameSessionに登録し、
ワールド内にあるPlayerStartオブジェクトを検索し、空いている場所から順に
Playerのポジションを決めることをしています。

PostLoginでは生成したPlayerControllerの初期化、ワールドの初期化、
共有オブジェクトの初期化などが行われています。

UE4内部ではOnPostLoginを呼び出すまでにこのような処理が行われており、
めんどくさいところをやってもらえていますが、問題が起こってから原因を
探すのに時間がかかってしまいました。

・じゃぁOnline SubsystemのSessionは?
Online SubsystemのSessionに関する公式サイトを貼っておきます。

この機能には CreateFindJoin等他にもいくつかありますが、
今回はCreate、Find、Joinの説明をします。
サーバアクセス、ホストへのアクセスなどが大まかに分かるように
シーケンス図を作成したので、貼っておきます。(クリックして頂くとキレイに見れるかと思います)

CreateSessionで(Sessionを作成します)
1.NamedOnlineSessionにSessionの設定を行います。
→接続できる人数、SessionのOwnerID・OwnerNameなどが設定

2.マッチングサーバへリクエストを行います。

3.ホスト側でOnCreateCompletedがコールバックで呼ばれSessionNameと成功失敗が返ってきます。

4.成功の場合はStartSessionを呼びマッチングサーバへSessionのスタートリクエストを送っていました。

FindSessionで(Sessionを検索します)
1.Sessionを検索する情報を設定し、マッチングサーバにリクエストを送ります。
→Sessionの検索件数、LANなのかInternet経由なのかも設定、その他いくつか設定

2.マッチングサーバに検索リクエストを送ります。
→自分のUserID(プラットフォームによって変わる)と検索するためのOnlineSessionSearchを使い設定

3.コールバックでゲスト側でOnCompletedが呼ばれリクエストの成功失敗の判定をしています。

4.その後JoinSessionへと続きます。

JoinSessionは(Sessionに参加します)
1.FindSessionで返されてきたSessions内の任意のSessionを選択します。

2.選択したSession情報を使用し、JoinSessionリクエストをマッチングサーバへ送ります。

3.コールバックとしてゲスト側でOnCompletedが呼ばれ、SessionNameとResultが返ってきます。

4.ゲストのPlayerControllerのClientTravelが呼ばれホストのワールドへ接続します。
→ClientTravel内ではPreClientTravelでクリーンアップやその他のタスクを実行できるよう
オーバーライドすることもできます。

※この時ホストではログイン処理が行われ上記に書いているログイン処理がされるということです。

Online SubsystemのSession……
ネットワークマッチングがあっというまにできるのでありがたいです。
しかし、Sessionを検索しようと思うと、PluginでAdvanced Sessions Pluginか、
多少自分で手を加えないと検索できないようなので注意です。

・まとめ
UE4でネットワークを実装中にOnPostLoginのトリガーで何か処理を書いている際に、
その処理が動いてないようでしたら、PlayerControllerが生成されているのか
確認してみてください。
この問題が起きて原因を見つけるまでにかなりの時間を使ってしまった経験があります………
みなさんはそんなことにならないようお気をつけください!
今回は上記の原因で起きておりましたが、別のことが原因で起きる場合もあるかと思いますので
その時はブログなどを書いて頂いて情報の共有をお願いします!!

今回はOnline SubsystemのSessionとLoginについて書きましたが、
ここまで理解するのに意外と時間を費やしてしまいました。
大半がインターネットで調べることはなくエンジンのコードを読んで勉強しつつでした。
まだまだUE4の情報は少なく作業をしていて、分からないところが出てくると、
調査、エンジンコードを読むのにかなりの時間を費やしてしまいます。
調べてそれらしきものを見つけるが、情報が古かったりなど使えないことも多々あります。
また、解説されているサイトが英語が大半ということもあり、
記事を読むのにも苦労してしまいます。
すらすら英語を読めるようになりたいものです…

さて今回はUE4のネットワーク関係での問題と解決策を紹介しましたが、
まだまだUE4を使用し、開発していくので、ネットワーク以外のことも紹介できるように
UE4に関しての知識、技術を勉強していきます!

・採用情報
クラウドクリエイティブスタジオでは一緒に働いてくれる方を募集しております!!
世界中で楽しんで頂けるゲームを一緒に作りませんか!?!?!?
採用情報