ゲーム作りに憧れ続けた人が、UE5で初めてゲームを作って公開までしてみた話

# はじめに
こんにちは、まいきーと申します！
表題の通り、UE5でウェーブ制TPSゲームを1本作りきってみたのですが
色々どんな感じだったのか、どんなことをしてどんなことを考えていたのか、制作を通して感じたこと等、せっかくなら発信しよう！という趣旨の記事です
制作を振り返って書き起こした体験記/回顧録のような感じなので制作ガイドやTips的な趣はないかもしれません
ゲーム制作の初心者がこんなことをしたんだなという読み物的に見てもらえれば幸いです
ちなみに筆者の現職はweb系開発者で、本格的なゲーム制作経験はおろか自分自身の制作物を作り、世に公開するということすら初めての経験でした
本当にやってみて良かったと思っているのでこの記事を読んでくれた人が自分もやってみよう！と思ってもらえたらとても嬉しいです！

ゲームのリンク

https://k117117117.itch.io/sunny-side-up

## 作ったゲームのクイックルック :eyes:
で、作ったゲームはどんなもん？ということで動画を貼ります

30秒プレイ動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/Y_befqRt4tE?si=VZO1sIobghCFxanx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

本人プレイ配信まとめ動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/-5M9yjJTh0U?si=ctxeBhh1BAH1Oz61" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

ゲームプレイ要素解説
<iframe width="560" height="315" src="https://www.youtube.com/embed/Jf4hED9seWQ?si=FybuLU6bXHHU4eOR" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

設定周り解説
<iframe width="560" height="315" src="https://www.youtube.com/embed/achSIWuRSVA?si=5EEH2Fmk6Olc7UzF" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

インゲームでの設定変更解説
<iframe width="560" height="315" src="https://www.youtube.com/embed/OPPIvxczaGE?si=aHSJnT0NpHIVs2ow" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 作ったゲームの概要と所感
実はこのゲーム僕が好きな配信者さん（https://x.com/WhoSunny_me ）のファンメイドゲームとして作りました
UE5で何かゲームを作ってみたいけど何を作ろうかなと思った時に、好きな配信者さんのファンメイドゲームを作るのは良いんじゃないかと思ったのです（人に話す時のインパクトもあるし）
制作そのものだけでなく、制作しきった後のことも楽しみにできて、モチベーションも保ちやすいだろうと思いました
本人にプレイしてもらっているところを配信してもらえたり
他のファンの人に遊んでもらって反応をもらえたり・・・
制作それ自体もとても充実感があって非常に楽しかったですが、作りきった後にもそういった楽しみが待っていると思うと
作りきるという目標達成の強い原動力になったし、制作のモチベーションをより高く保つことができました

ありがたいことに非常に良い反応を多くいただきまして、オタク冥利もとい制作者冥利に尽きる経験となりました
今回の制作の主目的はあくまでゲームを作るということであり、推しのためだけの制作という訳ではなかったですが、推しのゲームを作るエネルギーのあるオタクというコンテンツになれたことも良かったです

少し特殊なケースかとは思いますが、「自分が作ったゲームでユーザに喜んでもらう」というゲーム制作の醍醐味を、遊んでくれる人からダイレクトに感じることができて、ゲーム制作の素晴らしさを、凝縮された実体験として強く実感することができました
自身が携わった制作物でユーザに価値を提供する/価値を感じてもらう、そしてそれを目の当たりにして感じることができるというのは非常にやりがいを感じるなと思いました

## 筆者の経歴
こういう人でもゲームが作れるようになりました、ということで
他の人が再現性を検証できるように筆者の経歴を参考程度に記しておきます

<details open>
<summary>クリックして展開</summary>

| 項目 | 内容 | 備考 |
|:-:|:-:|:-:|
| 学歴 | 私大商学部卒 | 英語日本史小論文受験 <br>　英語は昔から好きで得意 <br> 数学は当時食わず嫌いしていた <br> ザ・文系でした |
| 理系的素養 | 高校卒業程度 | 数学は学部卒業前に算数から勉強し直した <br> 今となっては数学や科学、技術の話は好き |
| 仕事の経歴 | web系開発者 <br> 2024年現在実務経験5年目 | 新卒で俗に云う文系未経験から開発者として就職 <br> webフロントエンドからサーバサイドまで全般的に携わる <br> Windows、iOS、Androidなどのネイティブアプリケーションやクロスプラットフォーム開発も経験 |
| ゲーム制作経験 | 実務経験無し <br> 個人製作も今回が初 | UE4/5の極め本やYoutubeのチュートリアルなどでUE4/5の学習等は行っていた |
</details>

# 制作概要
制作期間：６ヶ月程度
実施内容：構想、ゲーム素材の用意、設計、実装、デバッグ、リリースなど主要な工程はほぼ全て？を実施
リリース後に見つかったバグ修正と修正パッチの配信なども行いました

| 作業工程 | 期間 | 概説 |
|:-:|:-:|:-:|
| 構想、調査、設計 | ２～３週間程度 | どんなゲームを作るかの構想<br>実装する機能の洗い出しや整理<br>開発方針の整理や策定<br>やることやらないことの整理等 |
| モデル作成やゲーム素材の準備 | １週間程度 | Blenderでプレイヤーキャラクターのモデルを作成<br>使用アセットの選定<br>著作権に関する調査等 |
| 実装/デバッグ | ５ヶ月程度 | コアメカニクスの実装<br>レベル作成<br>AIの実装<br>テストプレイと調整のイテレーション |
| リリース作業 | １週間程度 | リリースに際した著作権表示などの調査<br>itch.ioへのリリース |

**[構想調査設計]**
- ゲームの案出し/構想
- UE5でのウェーブ制TPS実装に関する情報収集と調査
- 開発方針の整理と策定
- 実装機能や仕様の洗い出し/整理と選定
- ゲームプレイデザイン/設計

**[モデル作成/ゲーム素材の用意]**
- Blenderを使ったプレイヤーキャラクターのモデリングとリギング
- ロゴ画面やアイコンの自作（このためにクリップスタジオを契約しました）
- 使用アセットの選定
- Skethfab等での追加の素材探しとUE5への導入（リギング等含め）

**[実装]**
- git/gitLFSでのバージョン管理の導入
- ALSv4への自作モデルの導入（IKリターゲティング）
- 自作モデルのアニメーションBPおよびアニメーションシーケンスの調整
- エンハンスドインプットの導入
- 銃撃システムの実装
- ブループリントインターフェースの実装
- マップ/レベルのグレーボックス作成
- マップのメッシングとレベルデザインの調整
- レベルBPやゲームモード/ゲームステートなどのロジック実装
- ゲームモード（難易度）のデータテーブル化
- 難易度ごとのパラメータ構造体の実装
- ゲームデザイン実装（ゲームプレイ、プレイフィールの検証と調整）
- テストプレイ/デバッグからのフィードバック（プレイヤーモデルの尻尾修正やAI、難易度の調整と追加、マップの修正など）
- AIの実装と調整（ビヘイビアツリー、ビヘイビアツリータスク）
- アニメーション通知を持ちいた足音イベントの実装とAI可聴時のロジック実装
- マテリアル関数を用いた敵の出現/消滅エフェクトの実装
- フィールドアイテムの実装（回復アイテム、ライフル武器）
- キーコンフィグ機能など設定周りの実装
- ユーザー設定の保存と起動時適用の実装
- UI、メニュー画面、設定画面等の実装
- クレジットのデータテーブル化
- ゲームインスタンスクラスへのCommonLoadingScreen制御の実装
- 処理負荷の軽減
不要なTickの無効化、アクタの可動性の設定、レベル内で到達可能性のないメッシュのコリジョン設定をNoCollisionにする等
- 翻訳/ローカライズ
日本語と英語をサポート

**[リリース]**
- 著作権関連の調査とクレジット作成
- ゲーム公開プラットフォームの調査と選定
- パッケージサイズの縮小（未使用アセットやプラグインの除去）
- itch.ioでのゲーム公開と公開ページの作成

## 開発環境、使用ツール等

<details open>
<summary>クリックして展開</summary>

| 項目 | 内容 | 備考 |
|:-:|:-:|:-:|
| OS | Windows 10 Pro |  |
| 動作対象OS | Windows |  |
| UE5 | バージョン5.0.3 | 製作開始時点(2023/5月頃)でALSv4がサポートしていた最新バージョンが5.0系だったのでこのバージョンでの開発となりました |
| IDE | Visual Studio Community 2022 | Incredibuildなども使用 |
| 言語 | Blueprint | C++プロジェクトとして作成しましたが <br> 結局実装は全てBlueprintで完結しました |
| バージョン管理 | Git, Git LFS, GitHub | UEのバージョン管理ツールの選択肢としてSVNやPerforce等があるということは知りつつ使い慣れているGitを選択しました |
| DCCツール | Blender | プレイヤーのメッシュ作成やSketchfab等からダウンロードしたメッシュデータに骨入れする際に使用 |
| 配布サイト | itch.io | itch.ioを選んだ一番の理由はアップロードするゲームのサイズ制限が寛容だったことです <br> webからアップロードする場合1GBまでの制限がありますがitch.ioが提供しているbutlerというCLIツールを使うと任意のサイズのゲームをアップロードして公開することができたのでitch.ioを選びました <br> あとはサイトも使いやすく公式のランチャーアプリがあることも良かったです |
| フローチャート作成 | draw.io | 処理フローの整理や敵AIの行動アルゴリズム(ビヘイビアツリー)の設計などに使用 |
| タスク管理 | Trello | やるべき作業を洗い出し、適切な粒度に分割しながら進捗管理を行うため <br> 仕事でもプライベートでも重宝しています |

**[Blueprintメインで開発した経緯について]**
BlueprintかC++どちらをメインにしてコーディングするか迷いましたが
作りきるということを考えた時に簡便さや情報の豊富さ入手しやすさ等を鑑みて
Blueprintメインでコーディングし、必要があればC++でコードを書くという方針にしました
後はALSv4が100% Blueprintで実装されていたためとりあえず合わせておくかみたいな感じもありました
結局Blueprintで全ての実装が完結してC++は使いませんでした
が、振り返ってみるとC++でコーディングした場合は差分管理がもっとしやすかったかもな～（多人数開発の時とか特に）もっと色んなAPIが使えたかもな～とか色々見えてくるものもありました
UEでの開発においてBPかC++かみたいな議論はよく目にしますがそれぞれに一長一短があり適切な使い分けが重要なんだろうなと思いました
個人的にはBPもC++も両方好きです

</details>

## 使用した機能、プラグイン、アセット等

<details open>
<summary>クリックして展開</summary>

| 項目 | 内容/選定理由等 | 備考 |
|:-:|:-:|:-:|
| Advanced Locomotion System V4 | 言わずと知れたキャラクター制御システムのアセット <br> キャラ制御やアニメーション周りの基盤がこちらを導入すればすぐに得られる上にクオリティが高く、これをベースにゲームに必要な機能などを実装していけばモチベーションも保てそうだと思ったのと、何より「作りきる」ということを重視した時に大きな助けになってくれること間違いなしと思ったので選定しました  | https://www.unrealengine.com/marketplace/ja/item/61b44ccf83234ba99cdada39a7460abc |
| Nanite | 目玉機能としてUE5から追加されたレンダリングに関わるシステム <br> LODを自動で行ってくれる上に描画負荷も最小限となるようにしてくれるとのことだったのでウキウキしながら有効化しました | Naniteを導入する際はスタティックメッシュはNanite有効にし、Megascansからメッシュを導入する際もNanite有効のものにする等が必要になります |
| Lumen | こちらも目玉機能としてUE5から追加された動的大域照明(動的グローバルイルミネーション)にかかわるシステム <br> Lumenを有効化すると光や影の表現がとても自然で美麗になるのが一目瞭然だったのでウキウキで有効化しました <br> またメッシュに割り当てられたマテリアルのエミッシブ値によって周囲を照らすことができるため光源としても使える、ライティングや光源(ライトアクター)描画にかかるコストを下げることもできたので選定しました | 動的大域照明(動的グローバルイルミネーション)とは光の反射を直接光だけでなく間接光なども考慮してリアルタイムに計算することで光や影の表現と描画を行う技術と解釈しています <br> なお動的というのは従来の事前に照明効果や影の計算を行ってテクスチャにしておくライトベイクといった手法とは異なりそれらをリアルタイムで行うことと解釈しています <br> これによってライティングにかかる負担を軽減しつつより説得力のある光と陰影の表現が実現できるようになったのではないでしょうか |
| Temporal Super Resolution | UE5から追加された超解像技術 <br> 選定した主な理由はゲームが提供するグラフィック設定の選択肢を抑えつつも見た目の品質が担保でき、実装面のコストも抑えることができると思ったからです <br> 一般的な画面解像度のオプションやアンチエイリアスのオプションを提供する場合Save Game Objectを使ったユーザ設定値の保存やゲームの設定オブジェクト（Game User Settings）を使った解像度の設定といった処理の実装を行う必要がありました <br> そこまでするよりかはTSRに絞るメリットを取った方が良いだろうと思った次第です | ゲーム画面のレンダリング時に画面解像度の70%等、小さい解像度でレンダリングを行ってからアップスケールを行うといった手法で描画負荷を抑えつつ良い品質を得られることのできる技術だと解釈しています |
| Enhanced Input | UE5から追加された新しい入力システム <br> UE5ではこちらがスタンダードになっていくということと入力の高度な制御、アセット(InputActionとInputMappingContext)による定義と管理ができるということで慣れたらこちらの方が柔軟性がありそうだと感じたので従来の入力システムではなくこちらを選定しました |  |
| MetaSound | UE5から追加された新しいオーディオシステム <br> 従来のオーディオシステムよりも使い勝手が向上しており、特にレベル中に再生するBGMのプロシージャル再生でその効果を実感できました <br> レベルの開始時に「イントロを再生➔ 以降バトルBGMをループ」といった風にしているのですが従来のサウンドキューなどを使うとキューの継ぎ目で音が途切れたり間が空いたりしたのですがMetasoundを用いることで途切れることなく自然に再生できるようになりました |  |
| Quixel Megascans | メッシュ、マテリアル、デカールなどゲームの素材がたくさんあるアセットライブラリ <br> UE5のエディタからMegascansのアセットを簡単に導入できる上になんと無料で使えてしまいます <br> Epic Games恐ろしや・・・ <br> 本当に手軽に様々なアセットを導入することができてゲームを豊かにできるので使わない手はなくものすごくお世話になりました | メッシュに関してはコリジョンが付いていないので必要であれば自分で付ける必要があります |
| Common Loading Screen | レベルのロード時等に表示するロード画面の実装を簡便に行えるようにしてくれるプラグイン <br> Lyra Starter Gameでも同プラグインが使われています <br> プロジェクト設定からロード時に表示するWidgetクラスを指定し、GameInstanceなどのクラスで処理を共通化すればスマートにローディング処理を実装できる感じだったので選定しました |  |


</details>

## 主に使用したアセット、ゲーム素材、素材サイト
<details open>
<summary>クリックして使用したアセットや素材を展開</summary>

| アセット名 | 内容 | 備考 |
|:-:|:-:|:-:|
| Anime City Suburbs | 街並みのアセット <br> レベルに使用 | https://www.unrealengine.com/marketplace/ja/item/e863584fbe004422a6de5c446c9912f5 |
| ArchViz Interior Vol.3 | 室内アセット <br> メインメニューの背景として使用 | https://www.unrealengine.com/marketplace/ja/item/f98f4c5e01144d89b58097122414b14e |
| Bank Building / Bank Interior + ULAT ( Modular Bank, Bank ) | 銀行のアセット <br> シャンデリアやATM等をレベルで使用 | https://www.unrealengine.com/marketplace/ja/product/bank-building-interior |
| Character Appearance and Dissolve | VFX、マテリアルのアセット <br> 敵キャラの出現/消滅時の視覚効果として使用 | https://www.unrealengine.com/marketplace/ja/product/character-appearance-and-dissolve |
| City Street Props | 看板のアセット <br> レベルの装飾に使用 | https://www.unrealengine.com/marketplace/ja/item/b1b4baf10ace45e4a2fb1d6cd964ffd8 |
| Farm Animal Sounds | 様々な動物の鳴き声を揃えたSFXのアセット <br> レベルクリア時のカットシーンで猫の鳴き声を使用 | https://www.unrealengine.com/marketplace/ja/product/farm-animal-sounds |
| Human Vocalizations | 声のアセット <br> 敵キャラを倒した時の声などに使用 | https://www.unrealengine.com/marketplace/ja/item/87fe49b1663348ee87a1fb1efab23ed7/questions |
| Interface & Item Sounds Pack | UIやアイテムに関するSFXのアセット | https://www.unrealengine.com/marketplace/ja/item/3954da9e19404633abe5d892e0911a06 |
| LowPoly Cats | ローポリお猫様のメッシュやアニメーションのアセット <br> レベルの装飾などに使用 <br> かわいい | https://www.unrealengine.com/marketplace/ja/product/lowpoly-cats |
| Luos's Eight elements | 火、水、雷などのVFX <br> 弾の軌道やヒット時の視覚効果などに使用 | https://www.unrealengine.com/marketplace/ja/product/luos-s-eight-elements |
| M5 VFX Vol2. Fire and Flames(Niagara) | 火炎のVFX <br> メニュー画面の装飾に使用 | https://www.unrealengine.com/marketplace/ja/item/c3ef89b2124849daa27dc829c8bb30e6 |
| City Environment Megapack vol 02 | 街並みのアセット <br> 日本の街並みのものをレベルに使用 <br> サイバーパンク作品に出てきそうな風情のある看板がグッドです | https://www.unrealengine.com/marketplace/ja/item/0932938b6b404b3f907bc3c967aa8270 |
| POLYGON - City Pack | 街並みのアセット <br> レベルの装飾に使用 | https://www.unrealengine.com/marketplace/ja/item/cee7a6790aec4b4fa9c8089a4f29e45c |
| Soul: City | 街並みのアセット <br> レベルに使用 <br> 九龍城のスラムっぽい感じでグッドです | https://www.unrealengine.com/marketplace/ja/item/6a5d9e9fa07a456b9a594db0ceb016c0 |
| StarSphere | 天球のアセット <br> レベルに使用 | https://www.unrealengine.com/marketplace/ja/item/03afa1548b5c4b49b3e5c8f4a0e44444 |
| Stylized Modular Character | モジュラーキャラクターシステムのアセット（複数のスケルタルメッシュで構成されるキャラクター） <br> 本ゲームではモジュラーシステムではなく宇宙服のメッシュを使いたかったのでそれを敵キャラに使用しました | https://www.unrealengine.com/marketplace/ja/product/stylized-modular-character/reviews |

</details>

<details open>
<summary>クリックして使用した素材のサイトを展開</summary>

| サイト名 | 内容 | 備考 |
|:-:|:-:|:-:|
| Unreal Engine Marketplace | Epic Gamesの公式アセットストア <br> 毎月無料でアセットを配布してくれるという大盤振る舞い振りがすごい <br> いつもお世話になっております | https://www.unrealengine.com/marketplace/ja/store |
| Sketchfab | 3Dモデルの投稿/配布サイト <br> 有料のものから無料のものまで色々あります <br> キャラクターの武器モデルはこちらのものを使用しました | https://sketchfab.com/feed |
| Free3D | こちらも3Dモデルの投稿/配布サイト | https://free3d.com/ |
| Soundsnap | SFXからBGMまで様々な音源素材があるサイト | https://www.soundsnap.com/ |
| Pixabay | 画像、動画、音源など様々な素材があるサイト <br> 音源探しに使いました | https://pixabay.com/ja/ |
| Freesound | SFXからBGMまで様々な音源素材があるサイト <br> UIがシンプルで使いやすいです | https://freesound.org/ |
| Peritune | フリーBGMを主に扱うサイト <br> レベルのBGMはこちらのものを使用 | https://peritune.com/ |
| SANKOU! font | 文字フォントのサイト | https://sankoufont.com/ |

</details>

## フォルダ構成
自作ファイル等のルートフォルダ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/2e0c578f-a52c-1775-a83e-22c96d7e4305.png)

<details open>
<summary>クリックしてtreeを展開</summary>

```
SUNNYALS\CONTENT\MYSTUFF
├─Audio
│  │  SCM_Main.uasset
│  │  SC_BGM.uasset
│  │  SC_Main.uasset
│  │  SC_SFX.uasset
│  │  
│  ├─BGM
│  │      8bitwin.uasset
│  │      kimagure_nyanko.uasset
│  │      MSS_8bitBattle.uasset
│  │      MSS_kimagure_nyanko.uasset
│  │      MSS_lets_party.uasset
│  │      PerituneMaterial_8bitRPG_Battle_intro.uasset
│  │      PerituneMaterial_8bitRPG_Battle_loop.uasset
│  │      PerituneMaterial_Lets_Party_loop.uasset
│  │      
│  └─SFX
│          MSS_DeadSFX.uasset
│          retro-laser-gun-shot.uasset
│          SA_SFX.uasset
│          
├─Blueprints
│  ├─Enemy
│  │  │  AIC_Space_Agent.uasset
│  │  │  BB_Space_Agent.uasset
│  │  │  BP_AIMantleForbiddenArea.uasset
│  │  │  BP_AI_Space_Agent.uasset
│  │  │  BT_Space_Agent.uasset
│  │  │  
│  │  └─BTComponent
│  │          BTTask_ChasePlayer.uasset
│  │          BTTask_CheckIfPlayerWithinRange.uasset
│  │          BTTask_ClearSoundLocation.uasset
│  │          BTTask_Fire.uasset
│  │          BTTask_ForgetPlayer.uasset
│  │          BTTask_GetRandomLocation.uasset
│  │          BTTask_MantleCheck.uasset
│  │          BTTask_RepositionIfAINearby.uasset
│  │          BTTask_SetFocus.uasset
│  │          
│  ├─Enum
│  │      E_Difficulty.uasset
│  │      E_GameStatus.uasset
│  │      
│  ├─Gameplay
│  │  │  BP_SunnyGameInstance.uasset
│  │  │  
│  │  ├─MainMenu
│  │  │      BP_MainMenu_GamemMode_SP.uasset
│  │  │      
│  │  ├─Raid
│  │  │      BP_Sanizaka_Raid_GameMode_SP.uasset
│  │  │      BP_Sanizaka_Raid_GameState_SP.uasset
│  │  │      Struct_ParametersDpendedOnDifficulties.uasset
│  │  │      Struct_Raid_RoundParameter.uasset
│  │  │      
│  │  └─Stroll
│  │          BP_Sanizaka_Stroll_GameMode_SP.uasset
│  │          
│  ├─Interface
│  │      BPI_Communicationable.uasset
│  │      BPI_CommunicationalUI.uasset
│  │      BPI_Interactive.uasset
│  │      
│  ├─Item
│  │      BP_ItemSpawnerBase.uasset
│  │      BP_ItemSpawner_BlasterRifle.uasset
│  │      BP_ItemSpawner_HealPack.uasset
│  │      
│  ├─Player
│  │      BP_ALS_Sunny_Character.uasset
│  │      BP_ALS_Sunny_Player_Controller.uasset
│  │      
│  ├─Prop
│  │      BP_CeilingLight.uasset
│  │      BP_Sunny_Display.uasset
│  │      BP_WoddenLamp.uasset
│  │      
│  ├─SavedSettings
│  │      BP_InputSaved.uasset
│  │      BP_LanguageConfig.uasset
│  │      BP_SoundConfig.uasset
│  │      BP_TermsOfuseAgreed.uasset
│  │      
│  ├─UI
│  │  ├─Common
│  │  │      WBP_CommonButton.uasset
│  │  │      WBP_ConfirmDialog.uasset
│  │  │      WBP_LanguageConfig.uasset
│  │  │      WBP_LoadingScreen.uasset
│  │  │      WBP_Template_Footer.uasset
│  │  │      WBP_TermsOfuse.uasset
│  │  │      WBP_TermsOfUseDialog.uasset
│  │  │      
│  │  ├─Gameplay
│  │  │      WBP_DeadDialog.uasset
│  │  │      WBP_EndDialog.uasset
│  │  │      WBP_LogoScreen.uasset
│  │  │      WBP_Victory.uasset
│  │  │      
│  │  ├─HUD
│  │  │      WBP_HealthBar.uasset
│  │  │      WBP_HUD_Crosshair.uasset
│  │  │      WBP_HUD_General.uasset
│  │  │      
│  │  ├─ListEntry
│  │  │  │  WBP_CreditEntry.uasset
│  │  │  │  WBP_GameModeEntry.uasset
│  │  │  │  WBP_KeyBindingEntry.uasset
│  │  │  │  
│  │  │  └─Item
│  │  │          BP_CreditEntryItem.uasset
│  │  │          BP_GamemodeEntry_Item.uasset
│  │  │          BP_KeyBindingEntry_Item.uasset
│  │  │          
│  │  ├─MenuUI
│  │  │      WBP_InputConfig.uasset
│  │  │      WBP_MainMenu.uasset
│  │  │      WBP_PauseMenu.uasset
│  │  │      WBP_SettingMenu.uasset
│  │  │      
│  │  └─WidgetStyle
│  │          CommonButtonStyle.uasset
│  │          
│  ├─Utility
│  │      BP_Utilities.uasset
│  │      
│  └─Weapon
│      ├─Gun
│      │      BP_BlasterRifle.uasset
│      │      BP_Gun_Base.uasset
│      │      BP_Raygun.uasset
│      │      
│      └─Projectile
│              BP_Projectile_Base.uasset
│              BP_Projectile_Enemy.uasset
│              BP_Projectile_Player.uasset
│              
├─Data
│  ├─Datatable
│  │  ├─Credit
│  │  │      Datatable_Credit.uasset
│  │  │      Struct_Credit.uasset
│  │  │      
│  │  └─Gamemode
│  │          Datatable_Gamemode.uasset
│  │          Struct_Gamemode.uasset
│  │          
│  └─Font
│          CP_and_U-Fo.uasset
│          CP_and_U-Fo_Font.uasset
│          
├─Effect
│  └─VFX
│      └─Light
│              LightOrb.uasset
│              Light_Explosion.uasset
│              
├─Input
│      IA_Aim.uasset
│      IA_Crouch.uasset
│      IA_CycleWeapon.uasset
│      IA_Equip1stWeapon.uasset
│      IA_Equip2ndWeapon.uasset
│      IA_Jump.uasset
│      IA_LookRightLeft.uasset
│      IA_LookRightLeftPad.uasset
│      IA_LookUpDown.uasset
│      IA_LookUpDownPad.uasset
│      IA_Move.uasset
│      IA_PrimaryAction.uasset
│      IA_Ragdoll.uasset
│      IA_Sprint.uasset
│      IA_SwitchShoulderCamera.uasset
│      IA_SystemMenu.uasset
│      IA_ToggleRotationMode.uasset
│      IA_ToggleShowRoundStatus.uasset
│      IA_ToggleWalk.uasset
│      IA_TurnRightLeft.uasset
│      IA_TurnRightLeftPad.uasset
│      IMC_InGame_KB.uasset
│      IMC_InGame_KB_Default.uasset
│      IMC_InGame_Pad.uasset
│      IMC_InGame_Pad_Default.uasset
│      PlayerBindableInputConfig_InGame.uasset
│      PlayerBindableInputConfig_KB.uasset
│      PlayerBindableInputConfig_KB_Default.uasset
│      PlayerBindableInputConfig_Pad.uasset
│      PlayerBindableInputConfig_Pad_Default.uasset
│      
├─Levels
│  │  LogoScreen.umap
│  │  MainMenu.umap
│  │  SaniZaka.umap
│  │  SaniZaka_Graybox.umap
│  │  Sanizaka_Raid.umap
│  │  Raid_StartSequencer.uasset
│  │  Raid_EndSequencer.uasset
│  │  Sanizaka_Stroll.umap
│  │  
│  └─_GENERATED
│      └─owner
│              略（自動生成メッシュ）
│              
├─Material
│      M_sunny_logo.uasset
│      
├─Mesh
│  ├─Raygun
│  │  │  Raygun_PhysicsAsset.uasset
│  │  │  Raygun_Skeleton.uasset
│  │  │  SKM_Raygun.uasset
│  │  │  
│  │  └─Material
│  │      │  Material_001.uasset
│  │      │  
│  │      └─texture
│  │              Material_001_baseColor.uasset
│  │              Material_001_normal.uasset
│  │              
│  └─Rifle
│      │  BlasterRifle_PhysicsAsset.uasset
│      │  BlasterRifle_Skeleton.uasset
│      │  SKM_BlasterRifle.uasset
│      │  SM_BlasterRifle.uasset
│      │  
│      └─Material
│          │  Green.uasset
│          │  Grey.uasset
│          │  White.uasset
│          │  
│          └─texture
│                  Green_baseColor.uasset
│                  Green_baseColor_ncl1_1.uasset
│                  Green_baseColor_ncl1_2.uasset
│                  Green_normal.uasset
│                  Green_normal_ncl1_1.uasset
│                  Green_normal_ncl1_2.uasset
│                  
├─Sunny（プレイヤーモデルに関するもの）
│  │  IK_Rig_Sunny.uasset
│  │  SKM_Sunny_UE4.uasset
│  │  SKM_Sunny_UE4_PhysicsAsset.uasset
│  │  SKM_Sunny_UE4_Skeleton.uasset
│  │  SM_Sunny_UE4.uasset
│  │  
│  ├─Animation
│  │  │  ABP_Sunny.uasset
│  │  │  ALS_AnimBP_Sunny.uasset
│  │  │  
│  │  └─BlasterRifle
│  │          Sunny_Props_BlasterRifle_Poses.uasset
│  │          Sunny_Props_BlasterRifle_Run_F_Arms.uasset
│  │          Sunny_Props_BlasterRifle_Sprint_F_Arms.uasset
│  │          Sunny_Props_BlasterRifle_Sprint_F_Impulse_Arms.uasset
│  │          
│  └─Material
│      │  MT_body.uasset
│      │  MT_Face.uasset
│      │  
│      └─texture
│              body.uasset
│              face.uasset
│              
└─Texture
    │  decal_image.uasset
    │  sunny_logo.uasset
    │  T_Sunny_Icon_Blue.uasset
    │  T_Sunny_Loading.uasset
    │  
    ├─Gallery
    │      gaming_480x270.uasset
    │      greeting_480x270.uasset
    │      wanted_480x270.uasset
    │      
    └─Thumbnail
            Raid_256x144.uasset
            Stroll_256x144.uasset
```

</details>

## 制作全般で意識/重視したこと
制作の方針や最初に決めたことなど

**[作りきって公開まですること]**
今回の制作ではこれを一番の最優先事項としました
他の制作方針もこれを軸に考えてとにかく作りきるということを重要視しました
本格的に制作に取り組むからにはどれだけシンプルで小さくても良いのでゲームとしてまとまった形で一本作りきって、堂々と「ゲームを一本作りました！」と言いたかったですし、開発者として制作物を一つ作り上げるところまで持っていったという事実を作りたかったという思いもありました
実際今回の制作を通してとても自信が付きましたし、開発者としての技術や知見もとても高まったと思います
作りきるということを重視して実装する機能の量を絞ったり、規模が大きくなって複雑にならないよう意識的にできるだけシンプルなゲームになるように構想や設計を行い、開発に割かなければいけないエネルギーや制作期間も膨張しないように意識しました
個人的に、どれだけ規模が小さくても、何か一つ、世に出すものの制作をやり遂げた人はもうその時点ですごいと思っています
制作には時間や労力といった多くのリソースやエネルギーが必要であり、完成まで持っていけるように継続していくということも簡単ではないと思っています
それをやり遂げた経験がある人はとても尊敬しますしそのすごさを今回の制作を通して実感することができました

**[ゼロから全部自分で作らない]**
上記の作りきるということに関連したことですがアセットなどを積極的に活用してゲームを作っていくことも最初に決めました（使用アセット等は上述）
ゲーム制作を助けてくれる素晴らしいアセットがかなり豊富にあって、これによって制作にかかる時間や労力などのコストを大きく削減できたと思っています
時間や労力といった開発資源は有限ですし制限がある中でゲームのクオリティを上げるためには使わない手はありませんでした
アセットに限らずとにかく開発のハードルを下げてくれるものがあれば積極的に活用してハードルを下げていこうといった方針は割と一貫していたと思います
というか個人開発で（しかも初めての）全部自分でやろうと思ったら超ハードモードと化していたでしょうしそうなることは想像に難くないですよね

**[ゲームが提供する体験や価値をユーザ、プレイヤー目線で考えて作る]**
ただ自分が作りたいゲームを作るのではなく
どんなゲームにしたら、どんな要素があればユーザは喜んでくれるか
どんな要素を盛り込めばユーザが喜んでくれる価値を提供できるか
といったことも強く意識していました
自分で作ったゲームを自分で面白いと思えるように作るのは前提として
自分以外のプレイヤーが遊んでくれた時にどういうところで楽しいと思ってもらうか
ゲームが提供する遊びの「楽しい」をもたらしてくれる要素や仕組みを客観的に考え、言語化した上で実装するように意識しました
ゲームが「楽しい」をもたらしてくれる要素や仕組みには様々なものがあり、ユーザが「楽しい」を感じる部分や条件も遊ぶ人それぞれで変わってくるかと思います
が、ゲームが「楽しい」をもたらす最も基本的かつ核となる要素/仕組みは
そのゲームのコアとなる遊びの部分の「仮説➔試行➔検証➔歓喜」という体験にあると思っています
そのゲームの遊びの部分がどれだけ「楽しい」をもたらしてくれるようになるかは
この「仮説➔試行➔検証➔歓喜」という体験を如何にデザインできるかにかかっているのではないでしょうか
こういったユーザに提供する体験や価値を、ゲームの完成形でどのように落とし込まれていればいいのかということをしっかりデザインしておくということは強く意識していました
今回制作したゲームが提供する遊びの上記性質は後述したいと思います

**[快適で無理をしない制作となるようにセルフマネジメントをする]**
どれだけ自発的に制作に取り組んでいようがやはり人間なので今日はあまり気分が乗らないなと億劫になることは当然あると思います
というか人間は機械ではないのでどんな活動であろうがそうなるのは必然であり避けることのできない問題でしょう
本当に好きなら寝食を忘れて、と思いがちですがどうやら生理的にそうなっていないようなのでそれをメタ認知できれば精神衛生的に安心できることが多くなると思います
なのでやる気が起きなくなる時も当然あるし
コンスタントに制作に取り組んでコンスタントに進捗を積み重ねていくことも
簡単ではないということをまず受け入れることが大事だと思います
そういう前提を受け入れていれば色々な場面で後ろめたさやストレスを感じることも少なくなると思います
そして肝心なのは**そういった問題に対してどう対処していくかを考えてセルフマネジメントしていくこと**だと思います
例えば気分が乗らない時はながら作業で進められるものはないか考えてみたり、ひとまず机に着いて5分作業してみて、それでも集中できそうになければ作業を止めて他のことをするようにするとか
そういった対応策を用意しておくようにしました
また、作業しなかった/進まなかったとしてもそれを後ろめたく感じないような考え方も取り入れていました
作業が進まなかった・・・とマイナスに考えるのではなく
休んで/リフレッシュしてエネルギーを回復出来て良かったとプラスに考えるようにする
といった感じです
あとは自分への期待値や作業/進捗のハードルを下げることも効果的だったと思います
昨日はこれだけ進んだのだから今日もこれだけ進めなきゃ、と思うのではなく
関数を一つ実装したとかどれだけ小さくても何かしら作業ができたらNICE、塵も積もれば山となるといった感じで
とにかくスモールステップ、ハードルは低く、進捗を気にしすぎない、ノルマ化しない、無理をしない、根詰めない
これらを意識して行動に落とし込んでいました
制作ペースや取り組み具合を無理してタイトにすればそれだけ心身の負荷やストレスも高まります
そうなると制作に取り組むこと自体にマイナスのイメージが付いてしまい制作をしたくなくなってしまいますから、そうなることは避けるようにしていました
制作に対して強迫観念が結びついてしまいそうなことは避ける、ストレスや心身の負荷になりそうなことは排除するといった感じですかね
制作状況と心身のストレスや負荷をしっかり評価して制作の取り組み方自体も見直していくことが大切です
怠惰な自分を許すというか人間は怠惰であるということを受け入れると低ストレスな開発体験にしていけると思います
自愛することを忘れず大切にしていきましょう

**[その他意識したこと]**
・どんどんやることを増やしてしまうとタスクが膨大になって終わりがなくなるので達成したい目標と照らし合わせてやらなくて良さそうならやらないを選択する
・意識的に休息を取る（アクティブレスト）
　個人的に休息を取ることは活動することと同じ位大切なことだと思っています
　休息を取ってエネルギーを回復してこそ継続的に活動していけるというものです
・運動して体を動かしたり、ゲームや外出などをしてリフレッシュすること
・制作してると一人で黙々と作業する時間が多くなるので友人と会話したりゲームしたり人と交流する機会を設けること
・自分でハードルを上げすぎないこと、なんならハードルの低い方を選ぶようにすること
　高い壁や課題に挑戦することも自分の成長に繋がるので歓迎すべきと思いますが今回は作りきるということを重視したのでそこは冷静に負荷がかかりすぎないよう意識しました

## 設計実装で意識/重視したこと

**[ゲームプレイフレームワークに沿った設計実装をする]**
UE5で本格的に一本ゲームを作ろうと思った時にまず直面した未知の事柄は
UE5で制作されるゲームのフレームワークやアーキテクチャといったソフトウェア的な構造に関する事でした
webアプリケーション開発にはLaravelやvue.jsといったwebフレームワークがあり、作成するアプリケーションのソフトウェア的な構造は使用するフレームワークによって雛形が提供されています（MVCモデルといったアーキテクチャパターンやその他デザインパターン等も含め）
筆者の経験ではアプリケーションを作る多くの場合それらに沿う形で実装を行っていくのが常となっていました
そのためUE5でのゲーム開発にもこのような枠組み骨組みはあるのか？あるとしたらどんなものなのか？ということがまず疑問に浮かびました
色々調べているとUE5にはゲームプレイフレームワーク（以下GPFW）と呼ばれる枠組みがあり、これをベースにゲームを作成していくのがスタンダード？だということにたどり着きました
GPFWとは何かを簡単に説明すると
ゲームのルール等を扱うGameMode、スコアといった状態の管理を担うGameState、プレイヤーの操作等を処理するPlayerController等々・・・
これらクラス群と、その連携によって成されるソフトウェアの枠組みのことです
そういったものがあると分かれば、後は安心して設計実装に取り掛かれました
何故ならそれに沿ってゲームを作っていけば少なくとも大きな失敗は避けられるはずだし
初めてのゲーム制作の中でもGPFWに沿ったアーキテクチャや構造、クラス設計をしていけばある程度見通しの良いソフトウェア構造になると理解できたからです
実際GPFWの構造や枠組み、考え方を通してゲーム制作における設計や実装の考え方等を自然と吸収することができました

**[情報の収集と精査は念入りに行う]**
筆者はweb開発者（n回目）でありゲーム制作のお作法に明るくないし、制作当初は知見やノウハウもありませんでした
初めてのゲーム制作への取り組みだったので当たり前ではありますが・・・できるだけ一般的なゲーム開発に近い形で開発をしたいと思っていました
なので何か機能を設計実装するといった際にできるだけ多くの情報に当たり、十分な候補の中から最適な選択肢を選び取るということを意識しました
Epic公式のリファレンス、Qiita、Zenn、業界で有名な方（おかずさんやalweiさんなど）の個人記事、極め本に始まり
StackoverflowやUnreal Engine Hub、英語のドキュメントやReddit、Youtubeなど
英語の一次情報も積極的に当たるようにしていました
こうした情報の深堀りを行うことでゲーム制作における知見やノウハウを蓄積できましたし、調べている中でも自分が知らなかった概念や知識、こういった方法で実装できるのか、といったことも知ることもできました
実際の開発にも十分に活用することができたので非常に効果的だったと思います
未知の領域でも自走/探索して適応していく姿勢と行動力には自信があるのですがそれが更に培われた気がしています
ちなみにゲーム開発に限らず英語の情報に当たれることは非常に恩恵が大きいと思います
英語だとそもそもの情報量も多い上新しい情報も多くヒットします
日本語で検索して欲しい情報が見つからなかった場合は英語の情報を検索してみると良いでしょう

**[よりスマートでベターな解決策を探求する]**
上記と少し被りますがこういった点も普段から意識しています
例えば敵AIを実装する際、最初はプレイヤーの存在を視錐台とレイで知覚するような方法での実装を試してみたのですが、これを自分でコードを書いて実装しようと思ったらどうも痒い所に手が届かないし拡張するのも大変そうだということが分かりました（この時点ではAIの知覚に関するコンポーネントが用意されているということは知りませんでした）
もっと簡便で良い解決策は無いかと「UE5 AI 視覚」のような形で検索するとPawn SensingやAI Perceptionというコンポーネントがあるということを知りました
ぱっと見ではPawn Sensingが直感的に使えそうに見えましたがもう少しよく調べるとAI Perceptionの方が柔軟性が高そうだということで今回の制作ではこちらを使うことにしました
こういった感じでよりベターなものは無いかということには注意を払っていましたね

# 制作でやったことの詳細
さて、ここからはやったことの詳細をいくつか紹介していきます
制作概要に示した様々なことをやってコードもゴリゴリ書いていましたが
実装したコードの解説ややったことの全てを書くことは残念ながらできないので
- 銃撃システムの実装
- 敵AIの実装
- ゲームデザインとその実装

の3点について書きます
筆者の持論と主観が多分に含まれていると思いますがどうぞお手柔らかに・・・

### 銃撃システムの実装
#### 銃撃システムの関連クラス
![銃撃システム図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/c39d61c6-df79-9584-ccf6-724663bac78a.png)
概観は上図のようになっています
エンハンスドインプットを使用しているため攻撃アクション（IA_PrimaryAction）のイベントハンドラは武器クラスに定義しています

#### 銃弾発射のロジック
攻撃ボタンを押す➔カメラからレイを飛ばす➔レイのヒット点に向けて弾を発射する
という流れで実装しました

##### ライントレース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/55a87cee-9021-6149-996a-b9c757507acc.png)
カメラが向いている方向にレイを飛ばすおなじみのやつです

##### 弾の発射
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/482e1886-7fe7-8e84-a0ef-246958839a3d.png)
レイの終点かそれより手前でアクタにヒットすればそこを着弾点とし、銃口の位置と着弾点への向きを持つトランスフォームを与えて弾を発射するといった感じで実装しました
**銃口からクロスヘアの中央（視線上にある点）に向かって弾が飛ぶようにしたかった**のでこのような実装になっています
当たり前のように感じる太字の箇所を強調して書いたのには理由があって、シューターにおける視線と射線のズレの問題を考慮した実装であることを説明するためです
![視線と射線.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/315d52d2-0767-b513-e0da-ab02db51687b.png)
普段シューター（TPSもFPSも）を遊んでいる時に意識することはほとんどないかと思いますが通常視点と銃口の位置は異なり視線と射線は一致していません
視点からレイを飛ばしてその当たり判定を弾の当たり判定とし、視線と射線を一致させているゲームもありますが、今回作ったゲームは
・即着ではなく、弾（プロジェクタイル）自体に当たり判定を持たせている
・TPSのため視点と銃口位置の離れ具合が大きい
といった理由で視点から飛ばしたレイの当たり判定をそのまま弾の当たり判定として使うのは適当ではありませんでした[^1]

[^1]:TPSでは視線は通っているが射線が遮られている場合に視線上の当たり判定をそのまま使うと見た目との不整合が起こりやすいです

では何故わざわざ視点からレイを飛ばして狙った対象の当たり判定を取っているのかと言うと**視線上にある射撃対象、つまり狙ったところに向かうように弾を飛ばすためです**
図のようにキャラや武器にとっての正面にそのまま弾を撃つと視線と射線の交点を除いてプレイヤーが狙った点と着弾点がずれてしまいます
なので狙ったところ（クロスヘアの中央）に弾が当たるようにするには視線上にある点に着弾点を一致させてあげるように弾を発射する必要があるのです
そうするために事前に視線上にある狙った点（射撃対象の位置）をレイのヒット結果から取得し、そこに向けて弾を発射させている（図の破線）といった感じになっています

ちなみに下図のように視線上の手前の点を狙った場合は射線も通っているので狙ったところに弾が当たりますが
奥の点を狙って弾を発射しても射線上に遮蔽物があり、このような場合は当然狙った点ではなく遮蔽物に弾が着弾します
視線は通っているが射線は通っていないという問題ですね
![視線と射線_遮蔽.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/c33df080-930a-b6cf-7983-4067451668d4.png)
この問題に対する対応策はゲームによって様々で
・キャラや銃口を着弾点に向かうようにする
・実際の着弾点に照準を表示する
といったものがあります
個人的にはMGS5の仕様がとてもスマートで遊んだ当時もスゴイ！と思いました[^2]

[^2]:この問題のタメになる解説はこちらhttps://togetter.com/li/969257

##### 効果音の再生とノイズイベントのレポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/15127231-2c6e-ce68-cedc-7183710b7da0.png)
弾を発射したタイミングで発射音を再生
また敵AIが発射音を知覚できるようノイズイベントを発行
敵AIの可聴範囲内で銃を撃った場合AIはこのノイズイベントの発生と位置を検知し、状態に応じた反応をするようになっています

### 敵AIの実装
#### 行動フロー
![敵AI行動フロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/3410cda3-b5cf-aad7-b5db-050638bf66ae.png)
敵AIの行動フロー/アルゴリズムは上に示すフローチャートに則って実装しています

#### 敵AIの関連クラス
![銃撃システム図_敵AI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/458c6179-54b1-082f-2462-f1f2f178d312.png)
銃撃ロジックについては後述のビヘイビアツリーの箇所に併記

#### ビヘイビアツリー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/bb15af36-3a99-a25a-a417-a81535db021b.png)
左から
・プレイヤー発見状態の行動ツリー
・プレイヤー未発見状態の行動ツリー
・プレイヤーが死亡した時の行動ツリー
スポーンした時点ではプレイヤー未発見状態なので探索行動を取り
発見したらプレイヤーへの接近や銃撃といった行動を取るようになります
（プレイヤーを見失ったら再度探索を行うようになります）

今回の制作で一番手を焼いたのがこのビヘイビアツリーの実装およびAIの行動制御でした
ビヘイビアツリーを用いたフローコントロールや扱いに慣れていないこともあり、あちらを立てればこちらが立たずという感じで
意図した通りの行動を取ってくれるようにビヘイビアツリーを組むのが中々難しかったです
正直ビヘイビアツリーの実装が綺麗に出来たかはあまり自信がありませんが初の試みだしある程度想定した動きをしてくれるのでヨシとしました

##### プレイヤー発見状態の行動ツリー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/b8293da1-70a3-c92a-3ae3-d826e64f20e3.png)
プレイヤー発見状態にある場合

1.射程範囲内で射線が通っていればその場で銃撃を行う
2.射撃中に他の敵AIが近くにいればランダムにポジションを変えながら撃つ
3.射程範囲外または射程範囲内でも射線が通っていない場合は**プレイヤーに接近しつつ**射線が通る位置まで移動する

といった感じになっています[^3]

[^3]:ちなみに筆者はこれをだるまさんが転んだアルゴリズムと呼んでいます
（動く時と止まる時の構造がなんとなくだるまさんが転んだに似ているなと思ったただそれだけですが）

2は敵AI同士が近い位置で（静止して）固まってだんごにならないようにするために盛り込みました
逆に敵AI同士が近い位置にいる場合ランダムに動いてくれるので動く敵を撃たないといけないというアクセントにもなってくれています
ただし射線が通る位置まで移動している場合は敵AI同士が近くにいてもリポジションをせず移動を優先します
なのでそれを利用すればウェーブ制シューターのテクニックの一つであるトレイン（敵を集めてだんごにする）を行うことも可能になっています

3の太字の部分は意外と大事なので強調しました
位置変更を行う際ランダムな位置に移動させてしまうと
・プレイヤーから更に離れた位置に移動してしまうことがある
・移動後の位置で射線が通っていない場合再度位置変更をする必要が生じこのループになってしまうことがある
といった具合で敵AIの行動が不自然になってしまうだけでなくゲーム的にも都合が良くありませんでした
プレイヤー的には発見後プレイヤーを倒しに来るような行動を取るのが自然だしゲーム的にもプレイヤーの近くに寄ってきてくれる方が都合が良いですよね
なので射線が通っていない場合のリポジションではランダムな位置に移動させるのではなく、とりあえずプレイヤーの近くまで寄るようにして射線が通るようになったら攻撃してくるといったアルゴリズムを「プレイヤーに接近する」という要素で実現するようにしました

なお敵AIが所有している武器で銃撃を行う際は武器のAIFireProjectileを呼び出します
AIFireProjectileはシンプルにBlackboardからプレイヤーの位置を取得しそこに向けて弾を発射するような感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/2669767a-bcaf-c4cd-1cc1-d96155389011.png)

##### プレイヤー未発見状態の行動ツリー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/27477538-8e16-411e-1f47-5f2a94f43ed4.png)
基本的にはランダムな地点間を移動してプレイヤーを視認するまで探索を行います
探索中に銃声やプレイヤーの足音を検知した場合はその音の発生箇所に向かいますがプレイヤーを視認できなかった場合は再度ランダム探索に戻ります

##### プレイヤーが死亡した時の行動ツリー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/d01ecaaf-961b-e910-77cd-63c0c167e526.png)
プレイヤーが死亡した場合敵AIは追跡や銃撃といった行動を中止しアイドル状態に戻ります

### ゲームデザインと実装
この節ではゲームデザインとその実装について以下の括りで書いていきます
- 「仮説➔試行➔検証➔歓喜」という体験
- 「仮説➔試行➔検証➔歓喜」の実装
- ゲームデザインを引き出すレベルのデザイン

#### 「仮説➔試行➔検証➔歓喜」という体験
ゲームが「楽しい」をもたらす本質的な仕組みや要素を突き詰めて考えると
その根っこや核にあるのは「仮説➔試行➔検証➔歓喜」という体験だと思っています[^4]
そのため随所にこの体験が伴うようにデザインを行い実装していくことを意識しました

[^4]:ゲームは何故楽しいのか、楽しいと感じる物事は何故楽しいのか？ということを自分なりにずっと考えていたのですが、自分が考えていたことを綺麗に整理してくれたのが「ついやってしまう体験のつくり方」という本でした。https://amzn.asia/d/bwUZadT

もちろんゲームが「楽しい」をもたらしてくれる要素はそれだけではありません
現代のゲームはストーリー、アート、ビジュアル、音楽、世界観、他プレイヤーとの交流など様々な要素を織りなした総合的なエンターテインメントとして作られており、楽しいを感じさせてくれるポイントは本当に色々なところにあります
しかしゲームをゲームたらしめる根底的な性質はやはりインタラクティブな遊びであるという点にあると思います
この遊びの楽しさを左右し決定づける一番大きな要素は「仮説➔試行➔検証➔歓喜」という体験であり、そして楽しい遊びは何故楽しいのか？を深ぼって考えてみると、そこには良くデザインされた「仮説➔試行➔検証➔歓喜」という体験がしっかり落とし込まれているということが見えてくると思います

例えばPONG
![Pong_Game_Test2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/d668d67c-6795-b340-1862-a387d051b0d5.gif)[^5]
[^5]:https://commons.wikimedia.org/wiki/File:Pong_Game_Test2.gif

パドルを操作して球を相手コーナーに打ち返し合って得点を競うというかなりシンプルなゲームですが、そこには上述の「仮説➔試行➔検証➔歓喜」がしっかりと伴っています
球の軌道や角度からパドルを置くべき位置を予測してパドルを動かす
球を打ち返す時に狙った角度や軌道で打ち返すためにパドルの特定の部分で打ち返すように位置を調節する
といった行動は
仮説を立てて試行を行いその結果を検証する（仮説が思った通りの結果に繋がったかあるいは異なる結果となったか）
試行結果が仮説で期待した結果となれば歓喜の感情を得られる、異なる結果となった場合は再度仮説と試行を行う
という体験が具現化されたものであると言えるでしょう
PONGは遊びという性質に特化したシンプルなゲームですがちゃんと面白いですよね
シンプルだからこそ遊びのデザインがしっかりしていれば楽しいものになるしその体験のデザインがいかに重要であるかを言語化して認知できる好例だと思います

#### 「仮説➔試行➔検証➔歓喜」の実装
ウェーブ制シューターは敵の数が多く、刻々と状況が変化していくといった特徴があります
不利な状況にどう対処して切り抜けていくか？多くの敵をどうやって捌いていくか？といった感じで、移り変わる状況や問題への対処、立ち回りを考えながらプレイしていく必要があり、これがウェーブ制シューターの醍醐味になっていると言えるでしょう
そのため、この立ち回りや臨機応変な対応が求められるというゲーム性にフォーカスして、それらの要素から「仮説➔試行➔検証➔歓喜」の体験を感じられるように実装を行っていきました
特にゲームプレイを通して立ち回りの重要性をプレイヤーに認識させ、立ち回りを駆使することでゲームのクリアに繋がるようなデザインを意識しました

キーとなったのは以下の要素です
・ゲームバランスと味付け
・遮蔽物の利用と射線の管理
・巡回ルートの発見と確立
・回復アイテム管理

##### ゲームバランスと味付け
ウェーブ制シューターである本ゲームの一番おいしいところ、つまり楽しいの根源である「仮説➔試行➔検証➔歓喜」の体験を最も感じられるところは上述の立ち回りの部分です
そのためプレイヤーが自然と立ち回りを駆使したり、おいしい部分を味わってもらいやすい行動を引き出したり等、ある程度行動を誘発してあげるようにゲームバランスの調整とデザインを行いました

上記のようなゲームバランスを実現する上で特に鍵となったのは与/被ダメージ量と敵の出現のさせ方です
本ゲームにおいてプレイヤーは基本的に1対多の状況に置かれますが、1対多の状況では倒されやすく1対少の状況なら敵を捌きやすくなるように与/被ダメージ量の調整を行いました
これには立ち回りの重要性を上げ、プレイヤーが1対多の状況から1対少の状況を作り出すような行動を取る、つまり立ち回りを誘発するといった狙いがあります
また敵の出現のさせ方に関しては以下のように調整しました
- レベル上のどの位置からも満遍なく出現させる
これによってプレイヤーがどの位置にいても四方八方から敵が接近してくる状況となるようにしました
- 同時に出現する敵の数に上限を設ける
これにより敵の数が理不尽に多すぎて状況のコントロールができなくなったり、立ち回っても1対少の状況が作れないということが無くなるようにしました
- 敵がプレイヤーに接近してくる
敵は四方八方から出現してくる上視認するまでプレイヤーに接近してくるため
同じ場所に留まっていると1対多の状況が続きかつ四方から射線が敷かれて不利となるようにしました
これによって自然と位置を変えながらプレイすることを誘発する狙いがあります

何も考えずただ敵を倒していけばクリアできるようなバランスにすると緊張感などの起伏がない大味な体験となる上ゲームの楽しい部分にプレイヤーが触れる機会が少なくなってしまいます
そのためゲーム内の行動のメリットデメリットをはっきりさせ、ウェーブ中の敵の捌き方をプレイヤーに考えさせるバランスとなるように意識しました

##### 遮蔽物の利用と射線の管理
上述のように本ゲームでは1対多の状況では倒されやすく、1対少の状況を作り出すことが重要となっています
この1対少の状況を作り出すという点で重要になってくるのが遮蔽物の存在とその適切な配置です
遮蔽物を利用すれば敵の銃撃を回避できるだけでなく、射線を絞ったり敵の導線を制御したり、1対少の状況/プレイヤーが有利な状況をプレイヤー自身が作り出しやすくなります
そのためレベル上の遮蔽物の多寡、配置、利便性などの塩梅がゲームバランスにマッチするように実装を行いました
以下に例を挙げます

スポーン地点
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/6276fc05-4d31-1652-616d-a917f2e12e15.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/7a99d109-92e6-d520-00f2-6db01b464268.png)
スポーン地点は開けており遮蔽物が無いとプレイヤーにとって一方的に危険な場所になる
遮蔽物があると各チョークポイント（左、真ん中、右の通路）からの射線を絞れるだけでなく接近してくる敵に対しても遮蔽物を用いながら戦いを仕掛けやすくなる

マップ中央
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/0e552bb6-31d7-576a-9e7e-20491238c33b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/58f37622-891c-134b-1eb8-e35c274f3932.png)
見た目では変化が少ないがこの場所は画像2枚目のように看板と柱が無いと長距離、高所、全方位からの射線が切りにくくなってしまう
そのため柱と看板を2枚目のように配置して射線を切りやすく、応戦しやすいようにしている

マップ端のL字エリア
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/50446c8b-d1f6-4cb9-b685-1546558fbff8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/16596cc0-4f0b-e776-2c53-beb222f8420c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/9399fbff-9fd3-e719-558e-e5f16e8982b5.png)
この場所はL字になっており端に行くほど十字砲火を受ける可能性が高くなっている
車と生垣を配置することで一方からの射線を切りやすくしている

##### 巡回ルートの発見と確立
こちらはウェーブ制シューターならではな要素ですね
ウェーブ制シューターでは基本的に敵が追いかけてくるためマップを動き回りながら敵を捌いていくことになります
そのため「こういうルートで通ると敵の群れを一つにまとめることができる、導線/射線を絞れる、敵をかわせる」といったようにマップ内の移動の効果を発見して活用するといった楽しみ方ができます
敵は四方から接近してくるため位置を変えながら戦うことが重要になりますが、移動によって生じる効果をはっきりさせることで攻略しやすいルートの探索と運用という行動を誘発させるようにデザインしました

##### 回復アイテム管理
マップの随所に回復アイテムを配置することで位置を変えながら戦うことのメリットを高めるようにしました
また回復アイテムは1ウェーブ毎に再出現するようになっており、各ウェーブで回復アイテムの残量と被ダメージ/HPを管理すれば、HPが犠牲になるかもしれないというリスクを取りつつ多少強引に敵を削りに行けるという選択肢を取れるようになりゲームプレイの幅を広げるようにしています

#### ゲームデザインを引き出すレベルのデザイン
お気づきの方もいるかと思いますので予め断っておくのですが、本ゲームのマップはOverwatchのカネザカというマップの構造を~~パクって~~ベースにしてところどころ改変を加えています（パロディやオマージュもいくつかあるので良かったら探してみてください）
本来自分でレベルを作っていくべきかとも思ったのですが、私の推しがOverwatchの配信者であり、Overwatchのマップに推しのキャラモデルを登場させたら喜ぶかもなという思いが先行してこのような形になりました（後は純粋に私自身カネザカが好きで作ってみたいというところもありました）[^6]
ゲーム的な理由ももちろんあって、カネザカはデスマッチ用のマップで構造的にもウェーブ制シューターとの相性が良さそうと思ったというのもあります

[^6]:商業目的でない（どちらかというと学習目的の）ファンメイドゲームといえ、ゲーム制作という文脈では是非が問われそうな部分なのかなとビクビクしてます...

さて、レベルのデザインはそのゲームでもたらしたい体験を引き出す非常に重要なものです
普段からゲームをよく遊んでいる人はマップのデザインが遊びに大きく影響することは肌で感じているのではないでしょうか
筆者は業務等でUXデザインなどにがっつり携わったことはありません（プログラマが本業）が、今回の制作で体験をデザインするということを経験しその重要性とすごさを改めて認識しました（プレイヤー目線でも制作者目線でも）
ゲームデザイナーやレベルデザイナーといった専門の職種が存在しているのも何ら不思議ではありませんね

それでは以下でマップ各所のデザインの意図を書いていきます

猫カフェの袋小路
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/26213303-b20f-24b7-0299-1c86e3755c06.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/ac208710-c668-f1e6-febf-89f30f145f61.png)
猫カフェの入り口は階段を上がり一本通路を通ったところにしかないため袋小路のようになっており、敵の導線がこの一本道に絞られるようになっています
また入り口から見て左右に窓がありプレイヤーはここから柵を飛び越えて脱出できるようになっています
この場所のこのようなデザインは敵を一か所に絞り、袋小路にひきつけながら削ることができる場所とし、また窓から脱出すれば敵との距離を離すことができる場所にするということを意図しています

開けっ広げの中央カフェ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/922b39ec-cd76-c17d-5cbf-3e9e568749de.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/06964fdf-e989-d69c-e9d9-d988c8ca56ad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/1980fd24-4241-60a0-e57b-a947640a3e23.png)
当初は全面壁で塞がれていましたがマップ各所の接続性向上、敵位置の視認性改善、射線確保のためにオープンビューで街の景色を楽しめる見晴らしの良いカフェに改装しました
ここのカフェの壁を開通させて窓にしたもう一つの大きな理由は敵から逃げる経路を増やすことです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/8bfb91fc-a311-3fbb-beac-8c2be2ef78c2.png)
このカフェ周りは角や死角になる場所が多く、また複数の通路が交わっているため敵に囲まれる可能性が高い場所になっています
そのためカフェの壁を開通して移動できる経路を増やすことでバランスを取るようにしました

参道
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/16390239-f148-c876-5b8d-d90f512eecc3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579137/c4efec3f-4c79-2563-0557-b08ce2c452e2.png)
鳥居から工事現場までの長い通路上にはほとんど遮蔽物を設置していません
この通路を活用することで敵をトレインしたり長距離からまとめて敵を削れるような場所にするという意図からこのようにしています
鳥居から工事現場に向かってスポーン地点に向かえば敵を一か所に集めた状態で撒いたり、逆に工事現場から鳥居に向かってマップ中央から任意の場所に逃げることで敵をかわしたりすることにも使えます

# 結び
最後に改めて感想を述べて締めたいと思います

まず率直に本当に非常に楽しくて充実感がすごかったです
ゲームが大好きでずっとプレイヤーという立場でしたが子どもの頃に憧れたゲームを作るということを実行できてなんだか感慨深かったです
もちろん体力も頭もすごく使うし大変で楽しいだけではありませんでしたが
自分のエネルギーを全てぶつけて取り組むことができる充実感はとてもとても大きく本当にやって良かったなと思っています
今回の制作を通していち技術者としても成長できたしゲームへの思いがより強くなりました
これからも色々挑戦と行動を続けていきたいと思います

# 参考にしたサイトや人、チュートリアルなど
alweiさん
おかずさん
九里江えめいくさん
ひろはすさん
DeathDiary（ALSv4などUE関連のチュートリアルを投稿しているYoutubeチャンネル）
UE備忘録本舗さん