主なコンテンツ

〜主なコンテンツ〜

1. Unityで製作したゲームと製作Tips
  1. 三月精チャレンジ(東方Project二次創作)
    1. 作り方
  2. 英語学習2D(オリジナルスマホアプリ)
2. UE4
3. ゲームアプリ見学
4. Bitbucket & SourceTreeでの一連の流れ
  1. 前半
  2. 後半
5. Tips
  1. UnityのTips
  5. SQL文のTips
  6. Final IK
  7. GearVR+Unity

2023年3月18日土曜日

42. Seamless Travel and Lobby

 アンリアル エンジンへようこそ。


マルチプレイヤー ゲームでは、何らかの方法で移動する必要があります。 このレクチャーでは、シームレスな移動がどのように機能するか、シームレスでない移動よりも優先される理由、およびそれが何を意味するかについて説明します。


遷移レベルを作成して、あるレベルから別のレベルに移動するたびにシームレスな移動を設定できるようにします。 十分な数のプレイヤーが集まったら、ロビーから実際のゲームに移動できるように、ロビー ゲーム モードを作成します。


それでは、まず非シームレス TRAVEL について話しましょう。 UNREAL ENGINE には、主に [シームレス] と [非シームレス] の 2 つの移動方法があります。


クライアントがシームレスに移動しない場合は常に、現在のサーバーから切断され、同じサーバーに再接続されます。 もちろん、これには切断と再接続に時間がかかり、異なるレベルに移動するたびに再接続するときに問題が発生する可能性があります. シームレスな移動を使用することをお勧めします。


初めてマップをロードするときに、シームレスでない移動が発生します。 サーバーに初めて接続するとき、およびマルチプレイヤー マッチまたはゲームが終了して新しいものが開始されるときも同様です。 これにはシームレスではない移動が含まれ、すべてのクライアントは切断してからサーバーに再接続して再度プレイする必要があります。


現在、シームレスな移動は、Unreal Engine での移動に好まれる方法です。 クライアントがサーバーから切断する必要がないため、よりスムーズなエクスペリエンスが得られます。


また、サーバーまたはサーバーが見つからない、突然プレイヤーが多すぎてプレイヤーが再参加できないなどの再接続の問題を回避するのにも役立ちます。


プロジェクトのシームレスな移動を可能にすることができます。 これはゲームモードで行います。 ゲーム モードには bUesSeamlessTravel というブール変数があり、これを true に設定してシームレスな移動を使用できます。

遷移マップまたは遷移レベルが必要です。 これは、あるマップから別のマップに移行するために使用できる単純な小さなレベルです。


遷移マップが必要な理由は、マップが特定の時点で常に読み込まれる必要があるためです。 したがって、遷移マップなしであるマップから別のマップに移動するには、最初のマップがまだロードされている間に 2 番目のマップをロードする必要があります。


そして、これには膨大な量のリソースが必要になる可能性があります。 そのため、遷移マップを使用して、既に存在していた元のマップを分解する前にそれをロードします。 移行マップに入ると、新しいマップをロードできます。両方の大きなマップを同時に存在させる必要はありません。


さて、[TRAVEL] とマルチプレイヤーについて説明してきました。 [TRAVEL]には複数の方法があります。 それらの方法の 1 つは、serverTravel を呼び出すことです。 これは、あなたの WORLD に属する機能です。 WorldServerTravel はサーバー専用です。 サーバー マシンは serverTravel を呼び出し、サーバーが serverTravel を呼び出すと、サーバーは新しいレベルにジャンプします。


接続されているすべてのクライアントは、サーバーが移動しているマップに従います。 サーバーは、接続されているすべてのプレーヤー コントローラーを取得し、プレーヤー コントローラー クラスに存在する関数 clientTravel を呼び出すことによってこれを行います。 clientTravel は、呼び出し元によって異なることを行います。


[クライアントから呼び出される] と、クライアントは [新しいサーバー] に移動します。 クライアントは、移動先の ADDRESS を提供する必要があります。 ただし、[サーバーから呼び出された]場合、これにより、プレーヤーはサーバーによって指定された[新しいマップ]に移動します。


次に、ロビー レベル用に作成するゲーム モードで serverTravel を使用します。 このようにして、十分な数のプレイヤーが参加すると、serverTravel を呼び出して、接続されているすべてのクライアントをサーバーに従ってゲーム マップに移動させることができます。


すでに 2 つのマップがあります。 gameStartupMap があります。再生を押すと、メニュー システム プラグインにあるメニュー ウィジェットが表示されます。


これまでのところ、プレイヤーはサーバーです。 マルチプレイヤーは存在せず、シングル プレイヤー ゲームでは唯一無二のプレイヤーがサーバーです。


ホストをクリックして Steam セッションを作成すると、最終的にプレイヤーはロビー レベルに移動し、他のプレイヤーが参加するのを待ちます。


これが私たちのロビーレベルです。 menuSystemPlugin は serverTravel を呼び出してこれを行います。 これでロビー レベルができたので、実際のゲーム レベルである新しいレベルに移動したいと思います。


そのために十分な数のプレイヤーが参加したら、参加者数をカウントできるロビー ゲーム モードを作成します。


それでは、新しいゲーム モード クラスを作成しましょう。 [C++ クラス] と [Blaster] に行きます。 ここで新しい C++ クラスを作成します。 それでは、右クリックして新しい C++ クラスを作成しましょう。[すべてのクラス] を選択し、ゲーム モードを検索します。


Unreal Engine には [game mode] と [game mode base] があります。 このプロジェクトでは [ゲーム モード] を使用します。 [ゲームモードベース] にはない追加機能があるためです。 そして、マルチプレイヤー ゲームを実装するときに、その追加機能についてさらに学習します。


[ゲームモード] を選択して、[次へ] を選択します。


ここで、このコース全体で複数のゲーム モードを作成しますが、それらはすべて独自のフォルダーに保存したいと考えています。


それでは、Blaster に Game Mode という名前の新しいフォルダを作成しましょう。 このゲームモードはロビー用です。


それでは、このロビー ゲーム モードを呼び出して、[クラスの作成] をクリックします。

クラスと独自のフォルダーを作成するときに見た、おなじみのメッセージが表示されます。 いいえをクリックするだけです。


これがロビー ゲーム モードです。 ゲーム モード フォルダにあることがわかります。


そして、robyGameModes.cpp のインクルードから「gameMode」を削除することで、コンパイラ エラーを取り除くことができることがわかりました。


ここで、lobbyGameMode は 1 つのことを行う必要があります。 ロビー レベルに接続または移動したプレイヤーの数を確認する必要があります。 一定の数が入力されると、これから作成する実際のゲーム マップに移動できます。


gameMode を継承した関数 postLogin を使用して、参加するプレイヤーを追跡できます。 この関数をオーバーライドします。


[lobbyGameMode.h] に public セクションを作成します。 そして、仮想関数 postLogin をオーバーライドします。 ログイン後はバーチャルボイドになります。


この関数は、NewPlayer というポインターである APlayerController を受け取ります。これはもちろんオーバーライドです。


それでは、PostLogin の関数定義を作成しましょう。 これが postLogin 関数です。


これまで見てきたように、これらの関数をオーバーライドするときは [super] を呼び出す必要があります。 [super::postLogin] を呼び出して、NewPlayer を渡します。

postLogin は、ゲームに参加したばかりの playerController に安全にアクセスできる最初の場所です。


現在、Game State と呼ばれるクラスが存在します。 実際、ゲーム モードには Game State という変数があります。 gameState 変数は gameStateBase を保持し、この Game State にはゲームに参加したプレイヤーの配列があります。 具体的には、playerStates の配列です。


ここで、このコースでの [gameStates] と [playerStates] の役割について説明します。 しかし今のところ、知っておく必要があるのは、ゲームに参加した playerState の数だけです。 これで、ロビーにいるプレイヤーの数がわかります。


ここで Game State にカーソルを合わせると、それが TObjectPointer であることがわかります。 実際、右クリックして gameState 変数の定義を選択すると、gameState が AGameStateBase をラップする TObjectPointer であることがわかります。


TObjectPointer は Unreal Engine 5 で導入された新しいタイプのラッパーで、これらのエンジン クラスの変数の一部に使用されます。 これで、開発中のエディターとエディターにいくつかの機能が提供されます。 Unreal Engine は、「これによりアクセス トラッキングが提供されるため、オブジェクトがいつ使用されているかを実際に検出できる」と述べています。


しかし、この目的のために知っておく必要があるのは、gameState がこの型 TObjectPointer を持ち、get 関数を使用して TObjectPointer によって格納された gameStateBase ポインタにアクセスできることだけです。


したがって、gameState 変数を取得して [.Get] を呼び出すと、AGameStateBase ポインターが返されます。


ここで、gameStateBased クラスを使用します。つまり、そのヘッダー ファイルをインクルードする必要があります。 また、gameStateBase は gameFramework に存在します。 それは gameStateBase.h と呼ばれます。


gameState にアクセスしたら、そのプレーヤー配列を取得できます。 これは単に playerArray と呼ばれる TArray です。 カーソルを合わせると、playerStates を保持するこれらの TObjectPointers の TArray であることがわかります。


この配列には、ゲームに参加した各プレイヤーの playerState が含まれています。 TArray であるため、配列内の要素数を int32 として返す TArray.Num 関数があります。 これは、ゲームに参加しているプレイヤーの数を示しています。

これで、numberOfPlayers という名前の int32 を作成し、この配列の長さと等しくなるように設定できます。


これで、誰かがゲームに参加するたびに、ポスト ログインが呼び出され、この整数のプレイヤー数が参加したプレイヤーの数を示すゲーム モードが発生することがわかります。


これで、この数をチェックして、ゲームに参加しているプレイヤーの数を確認できます。 プレイヤーの数が一定数に達すると、新しいレベルに移動することを決定できます。 それが私たちがやりたいことです。


そのため、プレーヤーの数が特定の数に等しいかどうかを確認します。 今のところ、[2] はハード コーディングされた [2] を使用します。 しかし後で、これに変数を使用します。 しかし、今のところ、これがどのように機能するかを確認したいと思います。


serverTravel を呼び出して、接続しているすべてのクライアントを特定のマップに移動できることがわかっています。 MAP に移動するには、移動先の MAP が必要です。


それでは、エディターに戻って、maps フォルダーに戻りましょう。 そして、移動先の新しいマップを作成したいと考えています。 それでは、新しいレベルを作成しましょう。


アセットには learningKitGames があり、maps フォルダーにあることがわかっています。 これが LearningKit_games_showcase です。 さて、私がこのレベルに進む理由は、多くのアセットで満たされているためです。これらのアセットを使用して、実際のゲームの見栄えの良いマップを作成できます。


ですから、このレベルを複製します。 このレベルをマップ フォルダにドラッグし、[ここにコピー] を選択します。 Maps フォルダには、LearningKit_Games_Showcase があります。


これで改名します。 これが、ゲームを開始するときに移動するマップであることがわかっています。 これを [blasterMap] と呼ぶことにします。 これで、移動先のマップができました。


ここで、robyGameMode に戻ります。プレイヤーの数が 2 人に達したら、すぐにそのマップに移動したいと思います。 これは、新しいワールド クラスの serverTravel 関数を使用して実行できます。


それでは、UWorld と言うワールドを取得しましょう。 それはポインタです。 このワールドを呼び出し、get world 関数を使用します。 そして、ワールドが有効であれば、単純にワールドを取得して serverTravel を呼び出すことができます。


ここで、serverTravel は移動先の ADDRESS を取ります。 これをサーバーから呼び出す場合、後で説明するように、ゲーム モードはサーバー上にのみ存在します。 したがって、私たちは間違いなくサーバー上にいます。


ゲーム モード クラスの場合、移動したいレベルへのパスを渡すだけで、接続されているすべてのクライアントがそのレベルに移動します。 これは FString なので、FString を作成し、その文字列を BlasterMap へのパスに渡します。


さて、このエディターで、そのパスが何であるかを知ることができます。 本当に、これは [maps] フォルダへのパスです。 [コンテンツ] の代わりに [ゲーム] という単語を使用します。 したがって、ここの FString では、「/game/maps/(レベル名)」と入力します。 これは blasterMap になりますが、このレベルに移動してリッスン サーバーとして指定する必要があります。 したがって、疑問符 (?) を使用して、アドレスにオプションを追加します。 そして、必要なオプションは「LISTEN」です。 これにより、この blasterMap がクライアントの接続先のリッスン サーバーとして開かれることが指定されます。

というわけで、プレイヤー数が 2 人に達したらすぐにブラスター マップに移動します。


ここで、シームレスに移動したいと考えています。bUseSeamlessTravel というゲーム モード クラスに存在するブール変数を設定することで、シームレスに移動できます。これを true に設定できます。


それでは、ここでコードをコンパイルしてみましょう。 これで、エディターに戻ることができます。 エディターで、これを設定するためにいくつかのことを行う必要があります。


まず、ロビー レベルに戻りましょう。生の C++ クラスを使用するのではなく、ロビー レベルのゲーム モードを設定する必要があります。 このためのブループリントを作成したいと思います。


それでは、blueprints に移動して新しいフォルダーを作成し、これを [gameModes] と呼びましょう。 [gameModes] では、新しい設計図を作成します。


右クリックして新しいブループリント クラスを作成し、[すべてのクラス] を選択して、robbyGameMode を選択します。 そして、[選択] をクリックします。 これを BP_lobbyGameMode と呼びます。


そして、lobbyGameMode で、それを開いてみましょう。 [デフォルトのポーン クラス] を選択できます。 BP_BlasterCharacter を選択します。 これで、BlasterCharacter としてロビーを走り回ることができます。


それをコンパイルして保存しましょう。 ロビー ゲーム モードを閉じます。 それをロビーのゲームモードとして設定します。


それでは【ワールド設定】に行きましょう。 [game mode override] ではドロップダウンを選択し、BP_lobbyGameMode を選択します。 ここで、[デフォルトのポーン クラス] が BP_BlasterCharacter であることがわかります。


ゲームモードをオーバーライドしたので、ワールドに実際のキャラクターは必要ありません。 [プレイヤースタート]があるので。 そして、このレベルに移動するプレイヤーは、プレイヤーの開始時にここにスポーンされます。 実際、私はプレーを打つことができます。 そして、私はここの真ん中にいます。


ロビーゲームモードには「シームレストラベルを使用」があります。 ここで、ログイン後にこれを true に設定しましたが、必要に応じてここで true に設定することもできます。 これは、すでに true に設定されていることを意味します。


これで、シームレスな移動の準備がほぼ整いました。 しかし、transitionLevel について話したことを思い出してください。 そのうちの 1 つが必要になります。


マップに戻り、遷移レベルを作成します。 ファイルの新しいレベルに行きましょう。 そして、私たちの遷移レベルは実際には何も必要としません。 実際、小さくてシンプルであればあるほど良いのです。 空のレベルを選択するだけです。 ここで [選択項目を保存] をクリックすると、まったく何もない完全に空のレベルが表示されます。 これは移行レベルに最適です。 ファイルをクリックして現在のレベルを名前を付けて保存し、マップに保存します。 これを [transition map] と呼び、[保存] をクリックします。 これで遷移レベルができました。

それを transitionLevel として使用したいことを Unreal Engine が認識していることを確認する必要があるだけです。 [編集] と [プロジェクト設定] に移動して、[プロジェクト設定] でこれを確認できます。


[遷移] を検索します。 [default maps] の下に表示されます。 [トランジションマップ]。 ドロップダウンを開いて、transitionMap を選択できます。


これで、Unreal Engine はトランジション マップをトランジション レベルとして使用することを認識します。 これで、シームレスな移動を使用するための設定がすべて完了しました。2 人のプレイヤーがロビーに参加するとすぐに、サーバーはポストのロビー ゲーム モードからサーバー移動を呼び出し、ログインすると、全員が blasterMap に移動します。


これを試してみたいと思いますが、その前に、あなたに挑戦があります。 現在、いくつかのマップがありますが、どれも退屈です。 また、Learning Games アセット パックには多くのアセットがあることもわかっています。 挑戦として、私たちのレベルをもう少し面白くしてほしいです。


まず、ゲームの startStartupMap にいくつかのアセットを追加します。 これは、プレイヤーがゲームを開いたときに表示されるマップです。 いくつかのアセットを使用して、見栄えを良くしてください。


ホスト ボタンと参加ボタンのあるメニュー ウィジェットのみが表示されることはわかっています。 そのため、少し創造性を働かせて、ゲームで表示される内容のプレビューをプレーヤーに少しだけ示します。


次に、ロビー マップにいくつかのアセットを追加していただきたいと思います。 さて、ロビーは通常、人が走り回れる小さなエリアです。それほど大きくはありません。 本当にあまりありません。 走ってジャンプして、他のプレイヤーが参加するのを待つだけのエリアです。


最後に、これはおそらく最も野心的な BlasterMap を作成してもらいたいものです。 これは、プレイヤーが実際にゲームをプレイするマップになります。これは、プレイヤーが互いに撃ち合うマルチプレイヤー マッチメイキング タイプのゲームになります。 いくつかの障害物をプレイして、ピックアップや武器、その他のゲームプレイの仕組みをどこに配置するかを考えてください。 高さの変化を試してみてください。 いくつかの隠れ場所を置きます。


全力で行く。 これには、好きなだけ努力してください。 それでは、ビデオを一時停止して、これらのマップを構築して見栄えを良くしてください。 そして、ゲームをパッケージ化してテストします。

わかった。 これらのレベルの作成を楽しんでいただければ幸いです。


ここにロビー レベルがあり、learningKitGames のアセットをいくつか使用しています。 これらの浮島を拡大縮小してここに配置し、Learning Kid Games マップにある花粉などのさまざまな効果を追加しました。 そして、浮島のいくつかを引きずり出し、そこに見えるようにしました。


ゲームのスタートアップ マップでは、キャラクターをここに配置しました。 これはキャラクターの BLUEPRINT ではなく、単なる SKELETAL メッシュです。 そして、詳細パネルを見ると、ここでは別のアニメーション、epic_character_Idle を使用していることがわかります。


したがって、プレイをクリックすると、これがプレイヤーがゲームを最初にロードしたときに表示されるものです。 メニューはまだありますが、キャラクターの素敵な背景ができたので、見栄えがよく、まとめるのにそれほど難しくはありませんでした.


ブラスター マップにも力を入れています。ブラスター マップには、learningKitGames レベルのすべてのアセットが含まれています。 私は単純にすべてのメッシュを取得し、それらを拡大してさまざまな方法で配置し、素敵なシューティング マップを作成しました。


うまくいけば、これがマルチプレイヤー メカニクスを実装するための素晴らしい環境を提供してくれることを願っています。このマップでは多くのプレイヤーが走り回り、互いに撃ち合うことができます。 素晴らしい。


これでテストできます。 これで、パッケージ ビルドでテストする準備が整いました。


さて、この blasterMap にはゲーム モードがないため、BlasterMap の gameModeBlueprint を作成します。 このマップのゲーム モード C++ クラスを作成します。 しかし、私たちはそれに到達します。 今のところ、必要なのは [ゲーム モード] だけなので、[デフォルトのポーン クラス] があります。


[BLUEPRINTS] と [gameModes] に行きましょう。 [Create a new blueprint class] を右クリックして、gameMode を検索します。 そして【ゲームモード】を選んでこちらを選択。 これを BP_blasterGameMode と呼びます。


BlasterGameMode で行う必要があるのは、[デフォルトのポーン クラス] を設定することだけです。 BP_BlasterCharacter を選択します。 playerStart がある場合は、ここにドラッグできます。このレベルのゲーム モードを設定するとすぐに、ここにスポーンします。


[ワールド設定] で、[ゲーム モード オーバーライド] に BP_BlasterGameMode を選択します。 そして、今プレイすると、このレベルで走り回るキャラクターができます。


それでは、このゲームをパッケージ化してテストしてみましょう。 これが私の Unreal Engine Project フォルダです。私が作成したビルド フォルダがあります。 先に進み、ここに存在する古いビルドをすべて削除しました。ここに新しいビルドを配置します。


[プラットフォーム]、[Windows]、[パッケージ プロジェクト] に移動します。 ビルドフォルダーを選択します。 それでは、これをパッケージ化するのに少し時間を割いてみましょう。


さて、パッケージングが完了し、ここに Windows フォルダーがあり、その中に [blaster.exe] があります。 これで、これを zip フォルダーに送信できます。 圧縮が完了したら、Google ドライブにアップロードできます。 さて、これが私がパッケージ化した最後のビルドです。 右クリックしてそれを削除し、圧縮した新しいパッケージ プロジェクトを Google ドライブにドラッグするだけです。


それが終わったらすぐに、別のマシンにダウンロードして、別のマシンで別の Steam アカウントにログインして、このゲームをテストできるようにします。 わかった。 プロジェクトのアップロードが完了し、別のマシンに移動してこの zip フォルダーをダウンロードし、展開しました。


もう 1 台のマシンでゲームを起動しました。別のテスターが参加する準備ができているので、自分のマシンでゲームを起動できます。 Windows フォルダに移動して [Blaster.exe] を実行し、ホストをクリックするだけです。


ここでは、ロビー レベルにいます。ロビー ゲーム モードは、ゲーム状態でそのプレーヤー配列にアクセスできるため、入ってくるプレーヤーの数をカウントしています。


そこで、テスターに他のマシンにログインして参加するように指示します。 そして、他のプレイヤーがここからロビー レベルに移動するとすぐに、ロビー ゲーム モードのポスト ログイン関数は、ゲーム内に 2 人のプレイヤーが存在することを確認し、その時点で serverTravel を呼び出し、2 人とも blasterMap に移動します。 わかった。 プレイヤーが参加し、ここでブラスター マップにシームレスに移行しました。すべてが見栄えがします。 これで、レベル内を走り回り、ゲームをプレイすることができます。


そのため、この講義では多くのことを取り上げました。 シームレスな移動と、それを実現する方法、および移行レベルが必要な方法について説明しました。


次に、実際のゲーム用のブラスター マップと、2 人のプレイヤーがロビーに参加するとすぐにサーバー トラベルを呼び出すロビー ゲーム モードを作成しました。 これで、Blaster マップに移動する準備が整いました。


十分なプレイヤーがゲームに参加するとすぐに、ゲーム自体にいくつかのマルチプレイヤー機能を実装できるようになります。


よくやった。


また後で。

Welcome to our Unreal Engine.


Multiplayer games are going to involve traveling in one way or another. And this lecture, we're going to discuss how seamless travel works and why it's preferred over non seamless travel and what that means.


We're going to create a transition level so that we can set up seamless travel whenever we travel from one level to another. And we're going to create a lobby game mode so that we can travel out of the lobby and into our actual game, Once we have enough players.


So let's first talk about non seamless TRAVEL. UNREAL ENGINE, There are two main ways to travel [seamless] and [non seamless].


Whenever a client travels non seamlessly, it disconnects from its current server and then reconnects back to that same server. This, of course, takes time to disconnect and reconnect, and there can be issues when reconnecting, whenever traveling to different levels. It's preferred to use seamless travel.


Non seamless travel occurs when loading a map for the first time. as well as when connecting to a server for the first time and when a multiplayer match or game ends and a new one begins. This involves a non seamless travel as well as all clients must disconnect and then reconnect to a server to play again.


Now, seamless travel is the preferred way to travel in Unreal Engine. It results in a smoother experience as the client doesn't have to disconnect from the server.


It also helps us to avoid any reconnection issues such as being unable to find the server or the server, suddenly having too many players and not allowing the player to rejoin.


we can enable seamless travel for our project. We do this in the game mode. The game mode has a boolean variable called bUesSeamlessTravel and we can set this to true now in order to use seamless travel.

We need to have a transition map or transition level. This is a simple small level that we can use to transition from one map to another.


The reason we need a transition map is because a map must always be loaded at any given point in time. So to travel from one map to another without a transition map, we would have to load the second map while the first one is still loaded.


And this can require a tremendous amount of resources. So we use a transition map and load that before deconstructing the original map that we were in already. And once we're in the transition map, we can then load the new map, and we don't have to have both large maps existing simultaneously.


Now, we've been talking about [TRAVEL] and multiplayer. There are multiple ways to [TRAVEL]. One of those ways is to call serverTravel. This is a function that belongs to your WORLD. WorldServerTravel is for the server only. The server machine calls serverTravel and the server jumps to a new level when the server calls serverTravel.


All connected clients will follow to the map the server is traveling to. The server does this by getting all connected player controllers and calling the function clientTravel, which exists on the player controller class. clientTravel does different things depending on who is calling it.


When [called from a client], the client will travel to a [new server]. The client must provide an ADDRESS to travel to. When [called from a server], however, this makes the player travel to the [new map] specified by the server.


Now we'd like to use serverTravel in a game mode that will create for our lobby level. And this way, when enough players join, we can call serverTravel and make all the connected clients follow the server into the game map.


we already have two maps. We have the gameStartupMap, which when we press play, we see our menu widget that we have in our menu system plug in.


Now thus far the player is the server. as there is no multiplayer going on and in a single player game the one and only player is the server.


Now when they click host and create a steam session, the end result is that the player travels to the lobby level to wait for other players to join.


Here's our lobby level. our menuSystemPlugin calls serverTravel to do this. Now we have our lobby level and we like to travel to a new level, the actual game level.


Once enough players join in order to do that, we're going to create a lobby game mode that can count the players as they come in.


So let's make a new game mode class. I'm going to go to [C++ classes] and [Blaster]. and we're going to create a new C++ class here. So let's right click create new C++ class, and I'm going to choose [all classes] and search for game mode.


Now Unreal Engine has [game mode] and [game mode base]. We're going to be using [game mode] for this project. as it has additional functionality that [game mode base] doesn't. And we're going to learn more about that extra functionality as we implement our multiplayer game.


So we're going to choose [game mode] and select next.


Now we'll be creating multiple game modes throughout this course, and I'd like to keep them all in their own folder.


So let's make a new folder here in Blaster called Game Mode. And this game mode is going to be for our lobby.


So let's call this lobby game mode and we'll go ahead and click Create Class.

Now we get this familiar message we've seen when we create a class and its own folder. We just need to click No.


And here's our lobby game mode. and we see that it's here in our game mode folder.


And we've seen that we can get rid of the compiler error by removing "gameMode" from the include here in lobbyGameModes.cpp.


now lobbyGameMode needs to do one thing. It needs to see how many players have connected to the lobby level or traveled to it. And once a certain number have come in, then we can travel to the actual game map that we're going to create.


we can keep track of the players coming in, using the gameMode inherited function postLogin. We're going to override this function.


So here in [lobbyGameMode.h] we're going to create a public section. And we're going to override the virtual function postLogin. So it's going to be virtual void post log in.


Now this function takes in APlayerController that's a pointer called NewPlayer, and this is, of course, an override.


So let's make our function definition for PostLogin. So here's our postLogin function.


And as we've seen, when we override these functions, we should call [super]. So we're going to call [super::postLogin] and pass in NewPlayer.

Now postLogin is the first place where it's safe to access the playerController that just joined the game.


Now there exists a class called the Game State. In fact, the game mode has a variable called Game State. The gameState variable holds a gameStateBase, and this Game State has an array of the players that have joined the game. More specifically, an array of playerStates.


Now we're going to get into the role of [gameStates] and [playerStates] in this course. But for now, all we need to know is how many playerStates have joined the game. And that'll tell us how many players we have in the lobby.


Now, when I hover over Game State, we see that it's a TObjectPointer. In fact, we can right click and pick the definition of the gameState variable, and we see that the gameState is a TObjectPointer wrapping AGameStateBase.


TObjectPointer is a new type of wrapper, introduced in Unreal Engine five, and it's used for some of the variables in these engine classes. Now this provides some functionality for when we're developing and the editor. Unreal Engine says "that this provides access tracking, which means you can actually detect when the object is being used".


But for our purposes, all we need to know is that the gameState has this type TObjectPointer and we can access the gameStateBase pointer that's stored by TObjectPointer using the get function.


So we would get our gameState variable and called [.Get] and that will return and AGameStateBase pointer.


Now we're going to be using the gameStateBased class and that means we're going to need to include that header file. and gameStateBase exists in gameFramework. It's called gameStateBase.h.


Now once we've access the gameState, we can get that player array. It's simply a TArray called playerArray. We can hover over it and see that it's a TArray of these TObjectPointers holding playerStates.


Now this array contains a playerState for each player who's joined the game. and being a TArray, it has the TArray.Num function which returns the number of elements in the array as int32. So this tells us how many players we have in the game.

Now we can make int32 called numberOfPlayers and set it equal to this arrays length.


And now we know whenever someone joins the game and they're resulting in post login being called and the game mode that this number of players integer will tell us how many players have joined.


Now we can check this number to see how many players are in the game. And if the number of players reaches a certain amount, we can decide to travel to a new level. So that's what we'd like to do. 


So we're going to check to see if number of players is equal to a certain number. For now, we'll just use [2] were hard coding, [2]. But later, we're going to use a variable for this. But for now, we'd just like to see how this works.


we know that we can call serverTravel to make all of the clients that have connected travel to a specific map. and to travel to a MAP, we need a MAP to travel to.


So let's hop back in the editor and go back to our maps folder. And we'd like to create a new map to travel to. So let's create a new level.


we know that in assets we have our learningKitGames and in the maps folder. Here's this LearningKit_games_showcase. Now, the reason I'm going to this level is because it's filled with lots of assets and we can use these assets to create a nice looking map for the actual game.


So I'm going to duplicate this level. I'll do that by dragging this level over to our maps folder and select [copy Here]. and now in our Maps folder, I have LearningKit_Games_Showcase.


Now I'm going to rename this. So we know that this is the map that we're going to travel to when we start the game. I'm going to call this [blasterMap]. So now we have a map to travel to.


Now, back here in lobbyGameMode, I'd like to travel to that map as soon as the number of players reaches two. And we can do that with the serverTravel function on the new world class.


So let's get the world we're going to say UWorld. That's a pointer. We'll call this world and we'll use the get world function. And if the world is valid, we can simply get the world and call serverTravel.


Now, serverTravel takes a ADDRESS to travel to. And if we're calling this from the server and as we'll learn later on, the game mode only exists on the server. So we are definitely on the server.


If we're in the game mode class, we can simply pass a path to the level we'd like to travel to and all connected clients will travel to that level. Now this is an FString, so I'm going to make an FString and for the string I'm going to pass in the path to BlasterMap. 


Now, here in the editor, I can find out what that path is. Really, it's just the path to the [maps] folder here. Except instead of [content], we use the word [game]. So here in our FString, I type a forward "/game/maps/(the level name)". Now this is going to be blasterMap, but we need to travel to this level and designate it to be a listen server. So we use a question mark (?) to add additional options to the address. And the option we need is "LISTEN". This will specify that this blasterMap will be open as a listen server for clients to connect to.

So now we're traveling to Blaster Map as soon as the number of players reaches two.


Now we'd like to travel seamlessly, and we can travel seamlessly by setting the Boolean variable that exists on the game mode class called bUseSeamlessTravel, We can set that to true.


Now let's go ahead and compile our code here. And now we can hop back into the editor. now in the editor, We're going to need to do a couple of things to set this up.


First, let's go back to our lobby level, and we're going to need to set our game mode for the lobby level now rather than using the raw C++ class. I'd like to make a BLUEPRINT for this.


So let's go to blueprints and create a new folder and call this [gameModes]. And in [gameModes], I'm going to make a new blueprint.


So let's right click, create a new blueprint class and I'm going to select [all classes] and choose lobbyGameMode. And Click Select. Now I'm going to call this BP_lobbyGameMode.


And in lobbyGameMode, let's open that up. We can select our [default pawn class]. I'm going to choose BP_BlasterCharacter. So we can run around in the lobby as the BlasterCharacter.


Let's compile and save that. And close lobby game mode. And we'll set that as the game mode for the lobby.


So let's go to [world settings]. And for [game mode override] will select the dropdown and choose BP_lobbyGameMode. And now we see that the [default pawn class] is BP_BlasterCharacter here.


Now that we've overridden the game mode, we don't need an actual character in the world. As we have a [player start]. And any players who travel to this level will be spawned right here at the player's start. In fact, I can hit play. And there I am, right here in the middle.


lobby game mode does have [use seamless travel]. Now, we did set this to true in post login, but we could also set it to true here if we like. That just means it'll be set to true already.


So we're almost set up for seamless travel. But remember I told you about a transitionLevel. We're going to need one of those.


So let's go back to maps and we'll create a transition level. Let's go to file new level. And our transition level doesn't really need anything in it. In fact, the smaller and more simple, the better. We can simply choose empty level. Now I'm going to click Save Selected and here's a completely empty level with absolutely nothing in it. This is perfect for a transition level. So I'm going to click file save current level as and save it here in Maps. And I'm going to call this [transition map] and click Save. So we have the transition level.

We just need to make sure that Unreal Engine knows that we'd like to use it as a transitionLevel. We can go to [edit] and [project settings] to make sure of this here in [project settings].


Search for [transition]. And we see under [default maps]. [transitionMap]. We can open the dropdown and choose transitionMap.


Now Unreal Engine knows to use our transition map as the transition level. Okay, so now we're all set up to use seamless travel and as soon as two players join the lobby, the server will call server travel from the lobby game mode in post, log in and everyone will travel into blasterMap.


Now I'd like to test this out, but before I do that, I have a challenge for you. We have several maps now, but they're all sort of boring. And we know that we have plenty of assets in the Learning Games asset pack. So for a challenge, I'd like you to make our levels look a bit more interesting.


First, add some assets to the game's startStartupMap. Remember, this is the map that players see when they open the game. So use some of the assets and make it look kind of cool.


We know that we're only going to see that menu widget with the host and join buttons. So use a bit of creativity and show the player a little bit of a preview of what they're going to see in the game.


Next, I'd like you to add some assets to the lobby map. Now, the lobby is generally a small area that people can run around in. It's not very large. There really isn't much there. It's just an area to run and jump and wait for other players to join.


And then finally, and this is perhaps the most ambitious I'd like you to create BlasterMap. This is going to be the map that the players will actually play the game in. This is going to be a multiplayer matchmaking type of game where players are shooting at each other. So play some obstacles and think about where you're going to be placing pickups and weapons and other gameplay mechanics. Experiment with changes in elevation. Put some hiding spots. 


Go all out. Put as little or as much effort as you want into this. So I'd like you to go ahead and pause the video and build up these maps and make them look good. And then we'll go ahead and package the game and test it out.

All right. So hopefully you had some fun creating these levels.


I have my lobby level here and I just use some assets from the learningKitGames. I took these floating islands and scaled them and positioned them here and added some different effects, like the pollen that was in that Learning Kid Games map. And I dragged out some of the floating islands so that we could see some of them there.


Now for my game startup map, I simply placed the character here. So this isn't the character BLUEPRINT, this is just the SKELETAL mesh. And if you look in the details, panel, you'll see that I used an animation aside here, the epic_character_Idle.


So if I hit play, then this is what the player sees when they first load up the game. We still have our menu, but now I have a nice background with the character there and so that looks pretty good and that wasn't too hard to throw together.


Now I also put some effort into my blaster map, and my blaster map contains all assets from that learningKitGames level. I simply took all of the meshes and scaled them up and positioned them in various ways to give myself a nice shooter map.


So hopefully this will provide me with a nice environment for when we implement some more multiplayer mechanics and I can have lots of players running around and shooting each other in this map, so I hope you put something together that's original and looks great and this is awesome.


We can now test this out. So I'm ready to test this out in a package build.


Now, since this blasterMap doesn't have a game mode, I'm going to make a gameModeBlueprint for the BlasterMap. we are going to make a game mode C++ class for this map. But we'll get to that. For now, we just need a [game mode] so we have a [default pawn class]. 


So let's go to [BLUEPRINTS] and [gameModes]. I'm going to right click Create a new blueprint class and search for gameMode. And choose [game mode] and select this. And I'm going to call this BP_blasterGameMode.


Now all I need to do in BlasterGameMode is set the [default pawn class]. I'm going to choose BP_BlasterCharacter. And now if we have a playerStart, I can drag one in right here, then we'll spawn right here as soon as we set the game mode for this level.


So in [world settings], I'm going to choose BP_BlasterGameMode for the [game mode override]. And if I hit play now, I have a character to run around in this level.


So let's package this game and test it out. Now, here's my Unreal Engine Project folder, and I have this build folder I created. I went ahead and deleted any old builds that existed here, and that's where I'm going to place my new build.


So I'm going to go to [Platforms], [Windows] [Package Project]. and select my build folder. So let's give this a minute to package.


All right, so packaging is complete and I now have my Windows folder here and inside I have [blaster.exe]. Now I can send this to a zipped folder. And once I'm done zipping it up, I can upload it to my Google Drive. Now, here's the last build that I've packaged. I'm going to right click and remove that and simply drag my new zipped up package project into my Google Drive.


Now, as soon as that's finished, I'm going to download it on my other machine and log my other machine into a separate steam account so that I can test this game out. Okay. So I finished uploading the project and I went to my other machine and downloaded this zip folder and extracted it.


And I've launched the game on my other machine and I have another tester ready to join so I can go ahead and launch the game on my machine. So I'm going to go to my Windows folder and execute [Blaster.exe] and I'm simply going to click host.


So here I am in my lobby level and my lobby game mode is counting the number of players that come in as it has access to that player array in the game state.


So I'm going to tell my tester to log in on my other machine and hit join. And as soon as that other player travels here to the lobby level, the lobby game mode post login function is going to see that there are now two players in the game at which point it will call serverTravel and we will both go to the blasterMap. Okay. So the player has joined and we've both transitioned seamlessly here into Blaster map and everything looks great. So now we can both run around in the level and play the game. 


So we've covered a lot in this lecture. We discussed seamless travel and how we can enable that and how this requires a transition level.


We then created a blaster map for the actual game and a lobby game mode that will call server travel as soon as two players have joined the lobby. So now we're set up to travel to the Blaster map.


As soon as enough players have joined the game and we can now implement some multiplayer functionality for the game itself.


Great job.


I'll see you soon.

0 件のコメント:

コメントを投稿