[UE4] 1ファイル(と関連しているアセット)だけをクックする

アンリアルエンジンはタイトルをリリースするときにターゲットプラットフォーム上で最適に動かせる形式に実行ファイルとアセットを変換します。
この中でアセットを変換する工程を**クック**と呼んでいます。

[公式ドキュメント](https://docs.unrealengine.com/ja/Engine/Deployment/index.html)

[[UE4] ビルドプロセスの流れ @donbutsu17](https://qiita.com/donbutsu17/items/f798d159049f82a277ee)

バージョンが更新されるたびに時間は短縮されておりますが、
それでも小規模なタイトルでの数分から数十分、大きなタイトルだと数時間ほど処理に時間が掛かります。

パッケージを作成してテストしたところ問題が見つかり、「あぁ・・・この1ファイルだけクックできればいいのに・・・」と思ったことがある方もいらっしゃると思います
今回は1ファイル(とそれが参照しているアセット)だけをクックする方法を記事にしてみました。

#クック処理はどこに記述されているのか

まずクック処理を行っているコードを見てみましょう。
クック処理のコードはずばり CookCommandlet.cppで始まり、メインループのコードはCookOnTheFlyServer.cppにあります。
ここで宣言されているUCookCommandletクラスを

```shell
UnrealEngine.exe -Run=Cook [いろいろオプション]
UnrealEngine-Cmd.exe -Run=Cook [いろいろオプション]
```

のようなコマンドラインオプションを加えて選択し実行しています。
UAT(UnrealAutomationTool)を使ってパッケージを作成している場合はUATが上記のコマンドを使ってクッカーを呼び出しています。

UCookCommandlet::Mainというメンバ関数がエントリーポイントなのですが
この関数の先頭でコマンドラインに指定されたオプションが解析されています。
その中に

```c++
	bCookSinglePackage = Switches.Contains(TEXT("cooksinglepackage"));
```
という**「クック・シングル・パッケージ」**とズバリそのもののオプションがあります。
早速試してみましょう！

#cooksinglepackageをテスト
最近のCookはどのファイルをクックしたかログを出さないモードになっているのでファイルごとにログを出すようにします。
`cook.displaymode`がそれです。こんな感じでDefaultEngine.iniに追記してやるといい感じです。

```
[ConsoleVariables]
cook.displaymode=2
```

UATを経由してクックする場合のコマンドはこんな感じです。
`-AdditionalCookerOptions="-cooksinglepackage"` AdditionalCookerOptionsを使ってクッカーにコマンドを渡すのがミソです。


```
e:\dev\UnrealEngine-4.25\Engine\Build\BatchFiles\RunUAT.bat -ScriptsForProject=D:/dev/UE425projects/Cook425/Cook425.uproject BuildCookRun -project=D:/dev/UE425projects/Cook425/Cook425.uproject -clientconfig=Development -serverconfig=Development -nocompile -nocompileeditor -ue4exe=E:\dev\UnrealEngine-4.25\Engine\Binaries\Win64\UE4Editor-Cmd.exe -utf8output -platform=Win64 -targetplatform=Win64 -cook -skippak -skipstage -noP4 -AdditionalCookerOptions="-cooksinglepackage"  -unversionedcookedcontent
```

結果は、、、ドンッ！！！

```
  CookResults: Warning: No files found to cook.
```

ファイルを指定してないんだからそりゃそうですよね！


#ファイルを指定する方法を考える
CookCommandletを眺めてみるとファイルを指定できそうなものがありません。mapなら`-map`オプションで指定できそうなんですが。。。


とコードを読んでみるとmapオプションはパスとして渡されて普通にアセットとして読み込まれているのがわかります。
試しに-mapを使ってアセットを指定してあげると、、、

コマンドはこんな感じで、先ほどのコマンドに `-map=/Game/Mannequin/Character/Textures/UE4_LOGO_CARD` を追加しました。

```
e:\dev\UnrealEngine-4.25\Engine\Build\BatchFiles\RunUAT.bat -ScriptsForProject=D:/dev/UE425projects/Cook425/Cook425.uproject BuildCookRun -project=D:/dev/UE425projects/Cook425/Cook425.uproject -clientconfig=Development -serverconfig=Development -nocompile -nocompileeditor -ue4exe=E:\dev\UnrealEngine-4.25\Engine\Binaries\Win64\UE4Editor-Cmd.exe -utf8output -platform=Win64 -targetplatform=Win64 -cook -skippak -skipstage -noP4 -AdditionalCookerOptions="-cooksinglepackage" -map=/Game/Mannequin/Character/Textures/UE4_LOGO_CARD -unversionedcookedcontent

```

結果

```
********** COOK COMMAND STARTED **********
HasMapsToCook /Game/Mannequin/Character/Textures/UE4_LOGO_CARD
Params.HasMapsToCook /Game/Mannequin/Character/Textures/UE4_LOGO_CARD
...(略)
  LogCook: Display: Max memory allowance for cook 16384mb min free memory 0mb
  LogCook: Display: Mobile HDR setting 1
  LogCook: Display: Creating asset registry
  LogCook: Display: Discovering localized assets for cultures: en
  LogCook: Display: Clearing all cooked content for platform WindowsNoEditor
  LogCook: Display: Sandbox cleanup took 0.055 seconds for platforms WindowsNoEditor
  LogCook: Display: Cooking /Game/Mannequin/Character/Textures/UE4_LOGO_CARD -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Cook425/Content/Mannequin/Character/Textures/UE4_LOGO_CARD.uasset
  LogCook: Display: Cooking /Engine/Animation/DefaultAnimCurveCompressionSettings -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/Animation/DefaultAnimCurveCompressionSettings.uasset
  LogCook: Display: Cooking /Engine/EditorResources/S_Actor -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EditorResources/S_Actor.uasset
  LogCook: Display: Cooking /Engine/EngineResources/WhiteSquareTexture -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EngineResources/WhiteSquareTexture.uasset
  LogCook: Display: Cooking /Engine/EngineResources/GradientTexture0 -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EngineResources/GradientTexture0.uasset
  LogCook: Display: Cooking /Engine/EngineResources/Black -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EngineResources/Black.uasset
  LogCook: Display: Cooking /Engine/EngineMeshes/Sphere -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EngineMeshes/Sphere.uasset
  LogCook: Display: Cooking /Engine/EngineSounds/Master -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EngineSounds/Master.uasset
  LogCook: Display: Cooking /Engine/EditorMaterials/MatineeGroCook/MAT_GroCook_Float -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EditorMaterials/MatineeGroCook/MAT_GroCook_Float.uasset
  LogCook: Display: Cooking /Engine/EditorMaterials/MatineeGroCook/MAT_GroCook_Anim -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EditorMaterials/MatineeGroCook/MAT_GroCook_Anim.uasset
  LogCook: Display: Cooking /Engine/EditorMaterials/MatineeGroCook/MAT_GroCook_AudioMaster -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EditorMaterials/MatineeGroCook/MAT_GroCook_AudioMaster.uasset
  LogCook: Display: Cooking /Engine/EditorMaterials/MatineeGroCook/MAT_ColorTrack -> D:/dev/UE425projects/Cook425/Saved/Cooked/WindowsNoEditor/Engine/Content/EditorMaterials/MatineeGroCook/MAT_ColorTrack.uasset
```

このアセットに関連しているアセットは読み出してしまうので完全に**シングル**というわけにはいきませんが、マップなどは読まれていません！

#まとめ

単体でアセットをクックしなおしてパッケージを作り直したい場合は`-cooksinglepackage`を使います。
UATを介してコマンドをクッカーに渡すためには`-AdditionalCookerOptions`を使います。
アセットの指定は`-map`を使います。-mapと書いてありますがアセットも指定可能です。