UE の Seamless Travel を利用してみた

内容としてはすでに多くの方がまとめてくださっている内容なので個人のログの域を超えていません 😇

利用した状況

ぷちコンに出した対戦ゲームは大きく以下の流れになっています。

  1. ログイン画面 (Epic Account でのログインのみ)
  2. メインメニュー画面 (セッション作成・一覧からの参加、キャラクターの選択など)
  3. ロビー画面 (参加ユーザー一覧、対戦マップ選択、対戦開始)
  4. 対戦画面

Level としては、1, 2 は同じレベル (MainMenuLevel)、3 はロビーレベル (LobbyLevel)、4 は対戦レベル群 (Stage*) となっていました。

これを UE の Session や Level の移動にあてはめると

画面 Level 処理
ログイン画面 MainMenuLevel
メインメニュー画面 セッション作成 Create Session
セッション一覧 Find Sessions
セッション参加 Join Session
ロビー移動 (セッション作成後) open LobbyLevel?Listen
ロビー画面 LobbyLevel 対戦開始 servertravel Stage*
対戦画面 Stage*

のようになります。(ちょっとこの書き方だと分かりにくいですね 😅)

つまり、 UE5 と Epic Online Services を BP のみで利用してみた - まとめとコード置き場 - You are done! での内容に対して、さらに「ロビー画面(のようなもの)」が間に挟まっている形です。

ちなみに、EOS のロビー機能は使っておらず、ここでもその説明はしません。というか使ってないのでできません・・・

ロビー画面が挟まることで変わることは、

  • 最初のセッション参加先 (つまりロビー)から、さらに対戦用のレベルにもう一段遷移しなければいけない
  • ロビーと対戦画面はやることが大きく異るため、GameMode も切り替える必要がある

の 2 点です。(後者は 1 つの GameMode でも実現可能かと思いますが、ここでは切り替える前提で進めます)

また今回の記事に関する点として、servertravel Stage* の箇所、つまり、ロビーから対戦画面への遷移時に Seamless Travel を利用したということです。

サンプルコード

GitHub - dany1468/EOSTest at seamless_travel

コードは以前の記事で利用した EOSTestseamless_travel branch として上げてあります。(Win10 と macOS Monterey / Xcode 13.4.1 で動作確認しています)

実行すると以下のような画面遷移となります。

youtu.be

以降の内容は上記のサンプルコードがベースになっています。

Seamless Travel

Unreal Engine でのマルチプレイヤー ゲームでの移動 | Unreal Engine ドキュメント

Unreal Engine は、可能な限りマルチプレイヤー ゲームにシームレス移動の使用をお勧めします。通常、ゲーム体験が一層スムーズになり、再接続のプロセス中に発生しがちな問題を回避できます。

「お勧めします」と書かれていますが、私の実行環境ではシームレスを有効にしないとそもそも servertravel が機能しませんでした。これに関しては私の方法が悪いのか、他の問題なのかの切り分けはできていません 😥

使い方自体はとても簡単で以下を行うだけです。

  • TransitionMap を用意する
  • GameMode の Use Seamless Travel を有効にする

TransitionMap の用意

上記のように Project Settings に設定します。TransitionMap は Empty Level で作成したままで私は使っています。

GameMode の Use Seamless Travel を有効にする

今回の場合は Lobby の GameMode から ThirdPersomMap (対戦画面を想定) に servertravel する際に有効にすればいいです。

もちろん、GameMode の属性自体を有効にしてしまってもいいと思います。

Seamless Travel を利用する上での注意

シームレストラベルの使い方とか - ひさめのあんりある日記

上記の記事が詳しいですが、OnPostLogin が呼び出されません。Seamless Travel の場合には、上に貼った公式ドキュメントにもある通り、再接続が無いため OnPostLogin は呼び出されないようです。

私が試した環境では以下のような順で関連するイベントが呼び出されました。

サーバー クライアント
Handle Starting New Player (クライアントのコントローラ)
OnSwapPlayerControllers (クライアントのコントローラ)
BeginPlay
Handle Starting New Player (サーバーのコントローラ)
OnSwapPlayerControllers (サーバーのコントローラ)

上記のように、クライアント側は何も呼び出されません。

Handle Starting New Player については以下に詳細がありますが、これを呼び出すと、デフォルトで spwan される pawn の処理が呼び出されなくなるので、キャラクターの spwan 処理を自前で記述する必要がでてきます。(今回のぷちコンの場合は逆に自前で呼び出したかったのでこちらを利用しました)
Game Mode と Game State | Unreal Engine ドキュメント

よって、セッションに接続する場合には OnPostLogin で良かったのが以下のように OnSwapPlayerControllers を利用するように変更されます。

ちなみに上図の Old PC はロビー画面からの遷移になるため BP_LobbyPlayerController になります。

余談: Player Start の選択

Handle Starting New Player の箇所で、今回参加したぷちコンではこちらを使ったとありましたが、その理由の一つに Player Start 位置の指定がありました。 (初期 spwan 位置に関しては、単に GameMode の Default Pawn ClassNone にするだけでも自動での spawn を止められます。他にも方法はあるかと思いますが。)

ここに関しては私の知識不足で実装当時は以下のように空いている Player Start を探して自前で spawn して posses させるという方法を取っていました。

もちろんこでも上手くいくのですが、今回の記事を書くにあたり、GameModeBaseChoosePlayerStart という override できる関数があることを知りました。

Player Start の Array は都度取得してもいいですが、以下のように事前に収集しておくこともできます。

やっていることは変わらないといえば変わらないのですが、単に Default Pawn Class のものを spawn させるだけならこっちの方が簡単だなという気づきでした。

参考にさせていただいた記事