[UE4] ShooterGameサンプルの、プロジェクト名/ファイル名/クラス名変更方法

#ShooterGameサンプルとは
[Shooter Game サンプル プロジェクト（UE4ドキュメント）](https://docs.unrealengine.com/ja/Resources/SampleGames/ShooterGame/index.html)
[Online MultiPlay Game Design（Epic Games Japanから提供されてる資料）](https://www.slideshare.net/EpicGamesJapan/online-multiplay-game-design)
ShooterGameとは、Epicから提供されてるC++サンプルプロジェクトの一つです。
Listen/Dedicated Serverの両モデルのサポート。GameSession、Matchmakingのハンドリング方法。Clientでヒット判定を行うInstantHit、Serverでヒット判定を行うProjectile。プレイヤーには即座にフィードバックを返して、ネットワーク遅延を気付かせないようにするノウハウ。
などなど、マルチプレイヤ―FPSの必須要素がつまっている重要なサンプルプロジェクトです。
市販の多くのUE4マルチプレイヤーゲームは、このプロジェクトをベースに作られているといっても過言はないと思います。

*（ShooterGameの解説も一度書いてみたいけど、めっちゃ長くなりそうなのでまた今度…）*

#何故プロジェクト名を変更するのか？
ぶっちゃけ、これは市販ゲームをリリースする必須事項ではありません。コンソールやモバイルは専用のパッケージングが行われますし、Windowsでもそのままでリリースされるのも珍しくはありません。
[ARKのSteam版はShooterGame.exeそのままでリリース](https://survivetheark.com/index.php?/forums/topic/461085-the-ue4-shootergame-game-has-crashed-and-will-close-problem/)されていますし、[Valorantはプロジェクト名はShooterGameのままで、実行バイナリだけリネーム](https://mobile.twitter.com/bvpeck/status/1270523563892633600)してるみたいです。*（私が過去に携わったタイトルでもShooterGameそのままでリリースした物もありました:sweat:）*
プロジェクト名を変更するメリットとデメリットを挙げるとするとこんな感じでしょうか。

#####メリット
- 名前を変えた方が新規プロジェクトっぽいし、何か気分的にすっきりする。
- リリース後に同業者から『あ、ShooterGame名前変えずにリリースしてるな:smirk:』と生暖かい目で見られずに済む。
- "Shooter"はコードネームとしては長いので、短い名前にした方がプログラミング時にタイプするワードが少なくなって作業効率が良くなる。

#####デメリット
- 結構面倒くさいし、プロジェクトが既に走った後に行うのはかなり大変。
- エンジンのアップデート時にAPIの変更に沿ってShooterGameサンプルもアップデートされるので、名前を変えてしまうと差分が取れなくなってアップデートがしづらくなる。特にUE5への移行時はコード側にも多くの変更が行われると思われる。EpicがShooterGameをUE5で動作保証してくれるかどうかは定かではありませんが…。

まあそもそもプロジェクト始動時にタイトルが決定してない事の方が多いと思われるので、プロジェクト名は2~3文字のコードネームにして作業を初めて、リリース時に実行ファイル名だけタイトル名に変える、というのが現実的かと思います。

#プロジェクト名/ファイル名/クラス名、全てを変えてみる。
という訳で、私がやった手順を書いておきます。ちゃんと動く保証はありませんので、自己責任でよろしくお願いします。
中途半端に名前を変更するのは逆に難しいので、プロジェクト名/ファイル名/クラス名、全てをリネームしています。

**UE4.26で、`Shooter`->`MY`に変更する**（MYは自分のコードネームに置き換えて下さい）

1. Epic Game Launcherから、ShooterGameをCreateProjectする。NameはShooterGameのままで。
1. /Binaries, /DerivedDataCache, /Intermediate, /Savedディレクトリを削除する。
1. /Content以外の全てのディレクトリ、ファイル名を部分リネームする（`Shooter`->`MY`）。私はFlexible Renamerを使わせてもらいました。
1. /Content以外の全てのテキストファイルに対して文字列置換を行う（`Shooter`->`MY`）。VisualStudioだと、/Buildが対象外になってしまうので、私は秀丸エディタを使わせてもらいました。
1. /Config/DefaultEngine.ini編集します。[/Script/Engine.Engine]の中の`+ActiveClassRedirects`ラインを後述のテキストに置き換えます。
1. MYGame.uprojectに、Generate Visual Studio project filesを実行。
1. MYGame.slnをVisualStudioでオープンして、Development Editorをビルド。
1. Editorを起動
1. ContentEditorで、\Content\UI\Styleの中の、全SlateWidgetStyleを部分リネーム（`DefaultShooter`->`DefaultMY`）。
1. Highrise, Sanctuaryレベルをオープンして、GameMode Overrideを`MYGame_TeamDeathMatch`にセット。
1. ContentEditorで、`ShooterEntry`レベルを`MYEntry`にリネーム。
1. MYEntryをオープンして、GameMode Overrideを`MYGame_Menu`にセット。
1. Editorを再起動して、Windowsパッケージを作成して動作確認。

```DefaultEngine.ini
[/Script/Engine.Engine]
+ActiveGameNameRedirects=(OldGameName="/Script/ShooterGame",NewGameName="/Script/MYGame")
+ActiveClassRedirects=(OldClassName="ShooterGameInfo",NewClassName="/Script/MYGame.MYGameMode")
+ActiveClassRedirects=(OldClassName="ShooterCamera",NewClassName="/Script/MYGame.MYPlayerCameraManager")
+ActiveClassRedirects=(OldClassName="SkeletalMeshComponent",OldSubobjName="ShooterPawnMesh0",NewSubobjName="CharacterMesh0")
+ActiveClassRedirects=(OldClassName="BTTask_HasLosTo",NewClassName="/Script/MYGame.BTDecorator_HasLoSTo")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterGame",NewClassName="/Script/MYGame.MYGame")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterCharacter",NewClassName="/Script/MYGame.MYCharacter")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterCharacterMovement",NewClassName="/Script/MYGame.MYCharacterMovement")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterBot",NewClassName="/Script/MYGame.MYBot")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterAIController",NewClassName="/Script/MYGame.MYAIController")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterWeapon",NewClassName="/Script/MYGame.MYWeapon")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterWeapon_Instant",NewClassName="/Script/MYGame.MYWeapon_Instant")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterWeapon_Projectile",NewClassName="/Script/MYGame.MYWeapon_Projectile")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterImpactEffect",NewClassName="/Script/MYGame.MYImpactEffect")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterExplosionEffect",NewClassName="/Script/MYGame.MYExplosionEffect")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterDamageType",NewClassName="/Script/MYGame.MYDamageType")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterShooterGame_TeamDeathMatch",NewClassName="/Script/MYGame.MY_TeamDeathMatch")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterPickup_Health",NewClassName="/Script/MYGame.MYPickup_Health")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterPickup_Ammo",NewClassName="/Script/MYGame.MYPickup_Ammo")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterProjectile",NewClassName="/Script/MYGame.MYProjectile")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterTeamStart",NewClassName="/Script/MYGame.MYTeamStart")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterChatWidgetStyle",NewClassName="/Script/MYGame.MYChatWidgetStyle")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterMenuItemWidgetStyle",NewClassName="/Script/MYGame.MYMenuItemWidgetStyle")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterMenuSoundsWidgetStyle",NewClassName="/Script/MYGame.MYMenuSoundsWidgetStyle")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterMenuWidgetStyle",NewClassName="/Script/MYGame.MYMenuWidgetStyle")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterOptionsWidgetStyle",NewClassName="/Script/MYGame.MYOptionsWidgetStyle")
+ActiveClassRedirects=(OldClassName="/Script/ShooterGame.ShooterScoreboardWidgetStyle",NewClassName="/Script/MYGame.MYScoreboardWidgetStyle")
```

#変更させる際の注意点
ポイントとしては、以下の通りです。これさえ守れば、まあ何とかなるんじゃないかと思います。

- Load時、実行時にエラーがでたら、とりあえず`+ActiveClassRedirects`を試す事。`+ActiveStructRedirects`はうまく動きませんでした。謎:thinking:
- /Content以下のファイルは、外部からリネームはしない、必ずContentEditorでリネームする事。

私がちょっとテストした感じでは動いてるように見えますが、もし実行時エラーなどが出たら上記の方法を使ってエラーを解決してみて下さい。