611.8K Views
December 21, 22
スライド概要
プロジェクトファイル
https://github.com/ProgrammingProntier/ThirdPersonShooter
超初心者向け UE5でゲームを1本つくろう! Programming.Prontier(); Metaseven
自己紹介 Programming.Prontier(); (@PProntier) Metaseven (@suramaru517) 大学でこの団体を立ち上げたり 個人でアクションRPGを作ったり Unrealな仕事をしたりしている大学生です 来年度からはゲーム会社で ゲームエンジニアとして働きます
Unreal Engineとは? フォートナイトで有名なEpic Gamesが開発している、リアルタイム3D制作ツール 美麗なグラフィックや、ブループリントというビジュアルスクリプティングシステムが特徴 ゲームだけでなく、建築・映像・自動車など様々な業界で利用されている Unreal Engine製のゲームの例 • フォートナイト • VALORANT • ファイナルファンタジーVII リメイク • テイルズ オブ アライズ
UE5のインストールとチュートリアル ゲームメーカーズさんの記事がわかりやすくておすすめです • 60分で出来る!無料でゲームづくりにチャレンジ! (こちらではUE5.0をインストールしていますが、今回はUE5.1を使用するので注意!) 公式のドキュメントやチュートリアルもおすすめです • Unreal Engine のインストール方法 • 初めての Unreal Engine 5
ゲームをつくろう 今回はUE5.1で三人称視点のシューティングゲーム (TPS) を作ります プレイヤーは弾を撃って敵を倒し、スコアを獲得します 敵はランダムに生成され、プレイヤーを追いかけます 敵にぶつかるとHPが減り、HPが0になるとゲームオーバーです 完成したゲームのプロジェクトファイルはGitHubでダウンロードできます なお、UE5.1以外のバージョンではうまくいかない可能性があります
サードパーソンテンプレートを作成する UE5.1を起動して ゲーム > サードパーソン を選択 スターターコンテンツにチェック プロジェクト名を “ThirdPersonShooter” などわかりやすい名前にして 作成しましょう
プレイする エディタが起動したら、上部にある▶をクリックするかAlt+Pでプレイしてみましょう WASDで移動、マウスで視点移動、スペースでジャンプができます エディタが重い場合は、こちらの記事を見ながら軽量化してみてください • 【UE5】低スペックPCのためのエディタ軽量化設定 - Qiita
おすすめ設定 (1/3) 設定は任意ですが、おすすめの設定を紹介します 編集 > エディタの環境設定 から設定画面を開きます
おすすめ設定 (2/3) アピアランス > アセットエディタの起動場所 をMain Windowに変更 アセットの編集画面が新規ウィンドウではなく、タブとして開くようになります
おすすめ設定 (3/3) 地域&言語 > 翻訳されたノードとピンの名前を… のチェックを外す ブループリントのノード名が英語になり、わかりやすくなります
プレイヤーの弾を作成する (1/2) 左下のコンテンツドロワーもしくは Ctrl+スペースでコンテンツブラウザを開きます コンテンツ/ThirdPerson/Blueprints内で 何もない場所を右クリックしてメニューを出し ブループリントクラスを選択します ブループリントクラスとはブループリントで 機能を追加・変更できるアセットのことです
プレイヤーの弾を作成する (2/2) 親クラスにはActorを選択し “BP_PlayerProjectile” という名前にします 親クラスとは自身の土台となる 機能を持ったオブジェクトです Actorはワールドに配置できる 最も基本的なオブジェクトです
弾の見た目を追加する BP_PlayerProjectileをダブルクリックで開き 左上にあるコンポーネントタブの追加ボタンから 球 (Sphere) を追加します コンポーネントとはブループリントに追加できる 拡張パーツみたいなものです 真ん中のビューポートに 白い球が表示されていればOK!
弾の見た目を調整する このままでは球が大きいので、大きさを調整します コンポーネントタブのSphereを選択した状態で 右にある詳細タブの拡大・縮小を XYZすべて0.25(4分の1)にします また球のコリジョン(当たり判定)は不要なため コリジョンプリセットをNoCollisionにしておきます
アセットを保存する 万が一エディタがクラッシュしてしまった場合 保存していない変更は失われてしまいます せっかく作ったものが消えてしまわないよう 開発中はこまめに保存しましょう 左上の保存ボタンかCtrl+Sで保存ができ 右下の保存ボタンかCtrl+Shift+Sで すべて保存ができます
弾を撃つ入力を作成する 弾を撃てるようにするため 入力の設定をします コンテンツ/ThirdPerson/Input /Action内で右クリックメニューから 入力 > 入力アクション を選択して InputActionを作成します 名前を“IA_Fire”とします
弾を撃つ入力を設定する コンテンツ/ThirdPerson/Inputにある IMC_Defaultを開きます Mappingsの⊕からIA_Fireを追加し IA_Fireにマウスの左ボタンを設定します これによりIA_FireのInputActionに マウスの左ボタンを紐づけることができます
弾を撃てるようにする (1/2) プレイヤーのブループリントである BP_ThirdPersonCharacter を開きます イベントグラフで右クリックすると ノード検索メニューが出てきます ノードとは何らかの処理が入った ブロックみたいなものです
弾を撃てるようにする (2/2) ノードを検索し、イベントグラフの空いた場所で画像のようにノードを追加します SpawnActorノードのClassにはBP_PlayerProjectileを選択します
プレイして弾を撃てるか確認する マウスの左ボタンを押して 弾を撃てるか確認します …どうなりましたか? 弾が出てきても動かないはずです これはまだ弾に球を追加しただけで 動くように設定していないためです
弾が動くようにする (1/2) では弾が動くように設定します BP_PlayerProjectileを開き コンポーネントタブの追加ボタンから ProjectileMovementを追加します ProjectileMovementは 弾の動きを簡単に設定できるように 用意されたコンポーネントです
弾が動くようにする (2/2) コンポーネントタブの ProjectileMovementを選択した状態で 詳細タブのInitialSpeedを2000.0 ProjectileGravityScaleを0.0に設定します これにより弾が重力の影響を受けずに 真っ直ぐ飛んでいくようになります
弾の寿命を設定する 今のままでは弾は永遠に残り続け、無限の彼方まで飛んで行ってしまいます 処理負荷の面で問題になるので、しばらくしたら弾が消えるようにします クラスのデフォルトを選択し、詳細タブのInitialLifeSpanを3.0に設定します これにより、弾は生成されてから3秒後に自動で消えるようになります
再度プレイして弾を撃てるか確認する マウスの左ボタンを押して、弾を真っ直ぐ撃てたらOK!
敵キャラクターを作成する 敵キャラクターのブループリントクラスを作成します 弾と同じようにメニューから作成することもできますが 今回はプレイヤーのキャラクターを複製して楽をします コンテンツブラウザでBP_ThirdPersonCharacterを 右クリックし複製を選択します 名前を“BP_EnemyCharacter”とします
敵のカメラとノードを削除する BP_EnemyCharacterを開きます プレイヤーにあったカメラや入力の処理は不要なため コンポーネントタブでCameraBoomと FollowCameraを削除し イベントグラフにある全てのノードを削除します 削除するには、右クリックして削除を選択するか 選択した状態でDeleteキーを押します
敵の見た目を変更する コンポーネントタブのMeshを選択した状態で 詳細タブのAnimClassをABP_Mannyに SkeletalMeshAssetを SKM_Manny_Simpleに変更します これにより見た目とモーションが QuinnからMannyに変わります MannyとQuinnはUE5の看板キャラクターです
敵を配置する BP_EnemyCharacterを コンテンツブラウザからビューポートに ドラッグ&ドロップして配置します プレイした時にわかりやすいように プレイヤーの開始位置の正面あたりに 配置しておきます
弾にコリジョンを追加する BP_PlayerProjectileを開き コンポーネントタブの追加ボタンから SphereCollisionを追加します 名前を“SphereCollision”とします またSphereCollisionの詳細タブで SphereRadiusを16.0に設定し コリジョンの大きさをSphereに合わせます
弾がダメージを与えるようにする (1/2) コンポーネントタブの SphereCollisionを右クリックし イベントを追加 > OnComponentBeginOverlapを追加 を選択します Overlapとはコリジョンに他のコリジョンが 重なることで、BeginOverlapは 重なり始めた時を指しています
弾がダメージを与えるようにする (2/2) 追加したイベントを使って、弾がダメージを与える処理を追加します ApplyDamageのBaseDamageには1.0を設定しておきます
敵がダメージを受けて死ぬようにする (1/2) BP_EnemyCharacterを開き、敵がダメージを受ける処理を追加します(続く)
敵がダメージを受けて死ぬようにする (2/2) (続き)
プレイして敵を倒せるか確認する マウスの左ボタンを押して弾を撃ち 敵を倒せるか確認します …どうなりましたか? 弾が出なくなった人は正解です なぜ弾が出なくなったのか 考えてみましょう
弾がプレイヤーに当たらないようにする 弾が出なくなったのは、弾がプレイヤーに当たって破棄されていたためです ApplyDamageの前にプレイヤーを除外する処理を追加し、破棄されないようにします
再度プレイして敵を倒せるか確認する 弾が敵に当たった時に、爆発のエフェクトや音とともに敵が消えればOK!
敵がプレイヤーを追いかけるようにする (1/3) 敵AIを動かすためには、ナビメッシュを生成する必要があります アクタ配置メニューから ボリューム > NavMeshBoundsVolume を選択します
敵がプレイヤーを追いかけるようにする (2/3) NavMeshBoundsVolumeが 床全体を覆うように 位置と大きさを調整します Pキーを押すとナビメッシュが 生成されているかを確認できます 緑色で表示されている部分が 敵AIの歩行可能な場所になります
敵がプレイヤーを追いかけるようにする (3/3) BP_EnemyCharacterを開き、プレイヤーを追いかける処理を追加します
プレイして敵が追いかけてくるか確認する 敵がプレイヤーを追いかけて、追いついた時は5秒待機した後再度追いかけたらOK!
敵がダメージを与えるようにする (1/2) BP_EnemyCharacterに 先ほどの弾と同じように SphereCollisionを追加します プレイヤーが敵の正面に ぶつかった時に当たるよう 胸の前あたりに配置します
敵がダメージを与えるようにする (2/2) イベントグラフを開き、プレイヤーにダメージを与える処理を追加します OnComponentBeginOverlapは先ほどの弾の時と同じように追加します
プレイヤーがダメージを受けるようにする (1/2) BP_ThirdPersonCharacter を開き、マイブループリントタブで 変数を作成します 変数は値を保存しておく場所です 変数名を“HP” 変数の型をFloat(小数) デフォルト値を10.0にします
プレイヤーがダメージを受けるようにする (2/2) イベントグラフを開き、ダメージを受けた後HPの値を出力する処理を追加します
プレイしてダメージを受けるか確認する 敵に当たった時に、10.0から1.0ずつ引いた値が画面左上に表示されていればOK!
プレイヤーが死ぬようにする (1/2) 先ほど追加したPrintStringの後に、死んだ時の処理を追加します(続く)
プレイヤーが死ぬようにする (2/2) (続き)
プレイしてプレイヤーが死ぬか確認する 敵に10回当たってHPが0になった時に、プレイヤーが倒れて操作できなくなればOK!
UIを作成する PrintStringの出力では残りHPがわかりづらいので HPバーを表示するUIを作成します コンテンツ/ThirdPerson/Blueprints内で 右クリックメニューから ユーザーインターフェイス > ウィジェットブループリント ルートウィジェットにUserWidgetを選択します 名前を“WBP_GameUI”とします
UIをデザインする (1/2) WBP_GameUIを開くと デザイナーモードの画面が開きます パレットタブでCanvasPanelを検索し デザイナーにドラッグ&ドロップして配置します CanvasPanelは他のウィジェットを 配置するための土台となるウィジェットです
UIをデザインする (2/2) パレットタブでProgressBarを検索して配置します 名前を“HPBar”とし、詳細タブで位置やサイズをお好みで調整します Percentでバーの割合を設定できますが、ここでは特に設定する必要はありません
UIを表示する (1/2) BP_ThirdPersonCharacterの BeginPlayの一番後ろに CreateWidgetノードを追加します ClassにWBP_GameUIを 設定した後、ReturnValueを 右クリックして変数へ昇格を選択し WBP_GameUIの変数を作成します
UIを表示する (2/2) 変数名を“GameUI”として、続けてUIを表示する処理を追加します
プレイしてUIが表示されるか確認する 画面にHPバーが表示されていればOK!
HPをHPバーに反映する (1/4) WBP_GameUIを開き、右上のグラフボタンから グラフ編集モードに切り替えます イベントグラフに移動したら ノード検索メニューでAddCustomEventを選択し カスタムイベントを追加します カスタムイベントは複数のノードを1つにまとめられるもので 他のBPから呼び出して使うことができます
HPをHPバーに反映する (2/4) カスタムイベントのノードを選択した状態で、詳細タブの名前とインプットを設定し カスタムイベントにHPバーを更新する処理を追加します
HPをHPバーに反映する (3/4) BP_ThirdPersonCharacterを開き、HPを複製して“MaxHP”の変数を作成します BeginPlayのUIを表示する処理の後に、追加したカスタムイベントを呼び出します
HPをHPバーに反映する (4/4) AnyDamageのHPを減らす処理の後にあるPrintStringを削除し 代わりにHPバーを更新するカスタムイベントを呼び出します
プレイしてHPがHPバーに反映されるか確認する プレイ開始時にHPバーが満タンで、敵に当たった時にHPバーが10分の1減ったらOK!
スコアを表示する (1/4) WBP_GameUIを開き、パレットタブからHorizontalBoxを配置します HorizontalBoxは複数のウィジェットを横に整列してくれるウィジェットです 詳細タブでSizeToContentにチェックを入れます
スコアを表示する (2/4) パレットタブから、Textを階層タブのHorizontalBoxに 2つドラッグ&ドロップして配置し、位置を調整します Textの詳細タブで片方のTextに“SCORE: ”、もう片方のTextに 適当な数字を設定します 適当な数字を設定したTextは 名前を“ScoreText”とし IsVariableにチェックを入れます
スコアを表示する (3/4) グラフ編集モードに切り替え、スコアの表示を更新するカスタムイベントを追加します
スコアを表示する (4/4) BP_ThirdPersonCharacterを開き、“Score”というIntegerの変数を作成します BeginPlayのUIを表示する処理の後に、追加したカスタムイベントを呼び出します
スコアを加算する (1/3) BP_ThirdPersonCharacterに “AddScore”というスコアを加算する関数を作成します 関数はカスタムイベントとほぼ同じもので DelayなどのLatentノードが使えない代わりに アウトプットを追加できます(ここでは使いません) 関数の詳細タブでIntegerのインプットを追加して 加算するスコアを指定できるようにします
スコアを加算する (2/3) AddScore関数に、スコアを加算してスコアの表示を更新する処理を追加します
スコアを加算する (3/3) BP_EnemyCharacterを開き、AnyDamageで自分を破棄した後に 作成した関数を呼び出し、プレイヤーのスコアを100加算するようにします
プレイしてスコアが加算されるか確認する 敵を倒した時にスコアが100加算されればOK!
ゲームオーバーを表示する (1/4) WBP_GameUIを開き CanvasPanelにTextを配置します 名前を“GameOverText”とし IsVariableにチェックを入れて アンカーを中央に設定します アンカーは、CanvasPanelにおける ウィジェットの座標の原点となる場所です
ゲームオーバーを表示する (2/4) 位置やText、色、フォントサイズなどをお好みで調整します 最初は非表示にしたいためVisibilityをCollapsedにします
ゲームオーバーを表示する (3/4) グラフ編集モードに切り替え、ゲームオーバーを表示するカスタムイベントを追加します
ゲームオーバーを表示する (4/4) BP_ThirdPersonCharacterを開き、AnyDamageの一番後ろで カスタムイベントを呼び出してゲームオーバーを表示し、5秒後にリセットするようにします
プレイしてゲームオーバーが表示されるか確認する 死んだ時にゲームオーバーが表示されればOK!
敵をランダムに生成する (1/3) 最後に、ゲーム中敵がランダムに 生成され続けるようにします 右クリックメニューから、Actorの ブループリントクラスを作成します 名前を “BP_EnemySpawner”とします
敵をランダムに生成する (2/3) BP_EnemySpawnerを開き、5~10秒毎に敵を生成する処理を追加します
敵をランダムに生成する (3/3) コンテンツブラウザから BP_EnemySpawnerを ドラッグ&ドロップして配置します 敵を生成したい複数の場所に 配置しておきましょう
敵をAIとして生成するようにする プレイして確認するとわかりますが、実はこのままでは生成した敵は動いてくれません 生成した敵を動かすためには、敵をAIとして生成する必要があります BP_EnemyCharacterを開き、クラスのデフォルトの詳細タブで AutoPossessAIをPlacedInWorldOrSpawnedに変更します
敵がカメラをブロックしないようにする 今のままでは敵がプレイヤーのカメラをブロックするため 敵が増えた時に視点が見づらくなってしまいます BP_EnemyCharacterの CapsuleComponentとMeshの両方の詳細タブで コリジョンプリセットをCustom Cameraのコリジョンレスポンスを無視するに設定します これにより、カメラが敵のコリジョンをすり抜けるようになります
プレイして敵がランダムに生成されるか確認する BP_EnemySpawnerから敵が5~10秒毎に生成されて、敵が動けばOK!
完成! これで一通り遊べるゲームが完成しました! ここからステージを作ったりして、このゲームを改造していくのも良いですし 今回学んだことを活かして、別のゲームを作ってみるのも良いかもしれません 今回はブループリントを中心に触ってきましたが これらはUnreal Engineの機能のほんの一部に過ぎません ぜひこれからも一緒にUnreal Engineを学んでいきましょう!
あとがき 本スライドは、Programming.Prontier();の勉強会のために 第5回ue4ハンズオンセミナー – SlideShare を参考にして作ったものです 3年前、Unreal Engineを初めて触った時に見た資料がこれで まさか3年後にこうなるとは思いませんでしたが… 作者のalwei (@aizen76)さんに深く感謝申し上げます!