[UE4] Editorのイテレーションを早くするTips(Lightmapビルド)

#1.はじめに
 前回に引き続きEditorのイテレーションを早くするためのTipsについて、今回はLightmapビルドです。
4.20.0で確認しています。

#2. Lightmapビルド

![2018-09-23_11h49_26.png](https://qiita-image-store.s3.amazonaws.com/0/101019/4e9fde03-2e80-066f-5065-a6d233ef8cc5.png)
Lightmapのビルドを実行すると上記の進捗度が表示されますが、このプロセスで実行される処理と改善方法を記載します。以下のドキュメントやスライドにおいてもビルドの仕組みなどが説明されています。

[[公式ドキュメント] Unreal Swarm](https://docs.unrealengine.com/en-us/Engine/Rendering/LightingAndShadows/Lightmass/Unreal-Swarm-Overview)
[[SlideShare] Lightmassの仕組み -Lightmap編-](https://www.slideshare.net/EpicGamesJapan/lightmass-lightmap-epic-games-japan)

##2.1. Lightmapビルドを早くするには?
公式ドキュメントからの抜粋ですが、アセットやシーンで出来ることは以下の通りです。コンテンツのクオリティに直結するため、基本的にはトレードオフとなります。

**【コンテンツでできること】** 
**① プレーヤーがアクセス可能なエリアにLightmassImportanceVolumeを追加する**
**② Lightmapの解像度を調整する**
**③ Foliage Tool Lightmapの解決策を有効にする**
**④ シーン中のActorとLightを削減する**

そしてビルドを実行するSwarm側では以下の点が改善に貢献します。

**【Swarmでできること】** 
**⑤ ローカルマシンの実行ジョブ数(LocalJobsDefaultProcessorCount)を増やす**
**⑥ リモートマシンの実行ジョブ数(RemoteJobsDefaultProcessorCount)を増やす**
**⑦ 出来る限りローカルマシンで実行する**
**⑧ 分散するマシンの台数を増やす、スペックを上げる**


##2.2. Lightmapビルド処理とその内容
以下にビルドの進捗度が更新される仕組みとビルドで行われる処理について記載します。

####●Lightmapビルドの進捗率
Lightmapビルドの進捗率は、
**進捗率(%) = Swarm完了タスク数(NumCompletedTasks) / Swarm総タスク数(NumTotalSwarmTasks) × 100**
の式に基づいています。

####●Lightmapビルドの対象となるTaskとCost


|#	|Task				|Cost		|TaskNum		|Condition	|
|:------|:---				|:---		|:---			|:---		|
|1	|VisibilityBucketGuids		|10000		|※3			|PrecomputedVisibility=true|
|2	|VolumetricLightmap		|10000		|※4	|VolumeLightingMethod<br>=VLM_VolumetricLightmap|
|3	|				|INT_MAX	|1|VolumeLightingMethod<br>=VLM_SparseVolumeLightingSamples|
|4	|MeshAreaLight			|1000		|1			|固定		|
|5	|DirectionalLight		|INT_MAX	|DirectionalLight数	|レベル上に存在時|
|6	|SpotLight			|10000		|SpotLight配置数		|レベル上に存在時|
|7	|PointLight			|10000		|PointLight配置数	|レベル上に存在時|
|8	|RectLight			|10000		|RectLight配置数		|レベル上に存在時|
|9	|BSP Surface Mapping		|TexelCount	|配置済StaticMeshの面数	|レベル上に存在時|
|10	|StaticMeshTexture Mapping	|TexelCount	|StaticMesh配置数	|レベル上に存在時|
|11	|LandscapeTexture Mapping	|TexelCount	|LandscapeComponent数	|レベル上に存在時|

※1 **TexelCount** = StaticLightingMappingのSizeX * SizeY
※2 **INT_MAX** = 2147483647
※3 BaseLightmass.iniで定義、Default:800
※4 (概算値)LightmassImportanceVolumeの総Voxel数 / VolumetricLightmapDetailCellSize

例えば”SpotLights”は、レベル上に配置されたSpotLight1つにつきTaskが1つ追加されて10000の実行コストが割り当てられます。この場合SpotLightが増えるごとにTaskとCostが追加されるため、Lightmapビルドの実行時間が伸びることになります。Taskは一般的にJob数と同じ意味を持ち、CostはSwarmで並列処理をできるだけ同じCostで処理するために利用されます。つまりCostは1Taskあたりの処理時間とも言えるため、SpotLightsのコストが”10000”に対してDirectionalLightsは”INT_MAX ”であることからDirectionalLightsは比較的ビルドに必要な処理コストが大きいということが言えます。このことから、DirectionalLightsを多用することはLightmapビルドを処理する時間が長くなることに貢献するということになります。

####●Lightmapビルドの処理完了
FLightmassProcessor::SwarmCallback
CompleteTaskはSwarmからのコールバックを受けて更新します。

![2018-09-23_19h26_02.png](https://qiita-image-store.s3.amazonaws.com/0/101019/b09f3c56-9221-3165-af51-feebf09ca64e.png)
上記は2台で分散したビルドの稼働状況を示すものです。デフォルトのJob数は6ですが上記は8にしているので、PCの殆どはライトビルドにタスクを割り当てています。Job数を減らすことでPCはライトビルドに割り当てる処理を少なくすることもできますが、ビルド時間が伸びます。

####●Lightmapビルドの分散による実行時間比較

|分散状況		|Work Time(s)		|
|:--------		|:------------------	|
|分散なし		|40.8			|
|分散1			|**32.7**		|
これはデスクトップPC1台と分散したノートPC1台でのビルド時間を比較したものなので、分散するPCの数を増やすことで更に時間を短縮することができます。


####●トラブルシューティング
[[Wiki] Swarm Agent Troubleshooting](https://wiki.unrealengine.com/Swarm_Agent_Troubleshooting)
大体のユースケースは上記のリンクに対処方法がありますが、firewallによる接続エラーのケースについて以下に記載します。

**[Tips] firewallによる接続エラー**
firewallによりpingが通らない場合、自分のPCから別のリモートクライアントは見えても一切のプロセスが実行されないということがあります。この場合、リモートクライアントから自分のPCに対してpingが通らないため、別のリモートPC上のSwarmにはping failedのエラーが出力されます。これは同一セグメントにあっても発生することがあるので、firewallの設定を一時的に解除することで解消します。この問題が発生している場合は、コマンドプロンプトのpingコマンドもタイムアウトが発生するため、firewallを解除後にpingが通ることを確認して、再度Lightmapビルドを実行します。


####●自動化
全てのLevelのLightmapビルドを行うと数時間かかるケースなどもありますので、Nightlyビルドなどで実行することも有効です。以下のリンクでCIからの実行や、複数のレベルを一括してライトビルドを行う方法が紹介されています。

[[UE4] ライトビルドをコマンドから実行しよう！](http://historia.co.jp/archives/7343/)