[UE4] ロード周りの設定と検証

この記事は[裏 Unreal Engine 4 (UE4) Advent Calendar 2016](http://qiita.com/advent-calendar/2016/ue4_inside)の19日目の記事です。

UE4ではBlueprintやMaterialEditorなどを利用することで素早くイテレーションを回すことができますが、
PIE(Play In Editor)時の起動時間やPersistentLevel間を移動する際のロード時間が長い点に関して、
もう少し改善できないかなと考えていました。
4.14で[「高速同期ロードシステムEDL(EventDrivenLoder)」](https://docs.unrealengine.com/latest/INT/Support/Builds/ReleaseNotes/2016/4_14/)というロードの高速化が期待できる機能が追加されたので、EDLを含めたロード周りの設定に関して幾つか検証してみました。

#設定内容

ロードに関連の設定はエディタのProjectSetting->Streamingから設定できます。
改めてソース見てて気づいたのですが、ここで「PackageStreaming」と書かれている項目はパッケージでの動作時にしか影響を及ぼしません。なので、4.14で追加されたEDLもパッケージでの動作時のみ有効となります(残念...)。

![set.png](https://qiita-image-store.s3.amazonaws.com/0/101019/a0da009f-ea7f-9694-f66d-d4c76bbd6868.png)

|#|項目|説明|
|:---|:---|:---|
|1|AsyncLoadingThreadEnabled|非同期ロード用のスレッドの有無設定|
|2|EventDrivenLoaderEnabled|高速同期ロードシステムEDL(EventDrivenLoder)の有効/無効設定|
|3|WarnIfTimeLimitExceeded|タイムアウト時の警告通知の有無設定|
|4|TimeLimitExceededMultiplier|タイムアウト時の閾値|
|5|TimeLimitExceededMinTime|タイムアウト時の警告通知の最短時間|
|6|MinBulkDataSizeForAsyncLoading|非同期ロードの最小データ容量|
|7|AsyncIOBandwidthLimit|非同期ロード帯域制限(MByte/s)|
|8|UseBackgroundLevelStreaming|レベル非同期ロードの許可設定|
|9|AsyncLoadingUseFullTimeLimit|非同期ロード時の読み込み制限時間の有無設定|
|10|AsyncLoadingTimeLimit|非同期ロード時の読み込み制限時間(s)|
|11|PriorityAsyncLoadingExtraTime|HighLevelPriority(WorldSettings)がある場合の非同期ロード延長時間|
|12|LevelStreamingActorsUpdateTimeLimit|レベルストリーミング中の1Actorの最大登録時間(ms/f)|
|13|LevelStreamingComponentsRegistrationGranularity|レベルストリーミング中にActorComponentを登録するために使用されるバッチ処理の粒度|

#検証
##方法

[SeemlessTravel機能](https://docs.unrealengine.com/latest/JPN/Gameplay/Networking/Travelling/index.html)を利用して、中間レベルで遷移先のアセット/レベルをロードします。開始時のレベル(StatMap)と中間のレベル(Maps)はデフォルトシーンを使用、遷移先のレベル([Elemental](https://www.youtube.com/watch?v=dD9CPqSKjTU))は学習用コンテンツから入手できるものを使用し、DevelopmentでパッケージしたBuildの動作を確認します。[SeemlessTravel機能](https://docs.unrealengine.com/latest/JPN/Gameplay/Networking/Travelling/index.html)はドキュメントにも記載されていますが、予めGameModeと中間レベルの設定が必要で、Standalone時の動作が前提となります。詳しくはリンク先をご覧下さい。

-検証手順
・以下の構成を用意し、0キーを押してレベル遷移させています。
　やりたいこととしてはStartMapからElementalへ遷移することで、SeemlessTravel機能によりElementalをオープンする前に中間レベル(Map2)で遷移先の読み込みを行います。ロード完了後、Map2→Elementalに自動で遷移します。

-検証構成
・レベル構成
![Test.png](https://qiita-image-store.s3.amazonaws.com/0/101019/eae6ae72-922d-c0f1-2617-11f8ac347194.png)

・StartMapのBP
![BP.png](https://qiita-image-store.s3.amazonaws.com/0/101019/1fd7e412-c8c2-d9de-3d2d-08633664c4d2.png)


-検証イメージ
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/YOUTUBE_VIDEO_ID_HERE/0.jpg)](https://youtu.be/SyhSD7pTPkc)


###(1) デフォルト設定
デフォルト設定の状態からレベル遷移を5回実行します。
他の設定と比較する用の基準値としています。

<結果>
__遷移完了してレベルロード完了まで平均時間：2.9sec__

![test1.png](https://qiita-image-store.s3.amazonaws.com/0/101019/c37d8231-1fea-e9ea-b669-7512c49214e2.png)

###(2) 非同期ロードスレッドを使用
項目1を有効化（AsyncLoadingThreadEnabled = true;）します。
この設定が無効の状態だとメインスレッドで非同期ロードも処理するのですが、有効にすることで非同期ロード専用にスレッドを立てて非同期ロード処理を行います。

<結果>
(1)よりも短時間でロード完了していることが分かります。
__遷移完了してレベルロード完了まで平均時間：1.9sec__
![test2.png](https://qiita-image-store.s3.amazonaws.com/0/101019/c570b47b-6ba2-878f-dac2-704e4a0a489e.png)


###(3) EDLを使用する
項目2を有効化（EventDrivenLoaderEnabled= true;）します。
が、4.14では[Editorからの設定内容が反映されない問題](https://issues.unrealengine.com/issue/UE-38347)があるため、直接コードを書き換えます。

AsyncLoading.cpp の145行目付近に設定項目があるので、
検証する際はGitHubからソースを落として以下の修正を行ってください。
※変更後はプロジェクトのRebuildが必要

```cpp:AsyncLoading.cpp
//static int32 GEventDrivenLoaderEnabled = 0;
static int32 GEventDrivenLoaderEnabled = 1;

```

<結果>
目に見えて早くなったというわけではないですが、(2)よりも平均して良い数値が得られました。
__遷移完了してレベルロード完了まで平均時間：1.7sec__
![test3.png](https://qiita-image-store.s3.amazonaws.com/0/101019/d0d8163f-5003-121d-6848-d7e020566575.png)



#さいごに
バージョンアップと共に色々な便利機能が追加されていますが、併せて様々な設定項目も追加されています。
バージョンアップ時にはエディタの設定項目の変化や、コンフィグの差分など、一度見直してみると良いかもしれませんね。


明日は@sinobuさんの「キャラクターについて何か書かせてもらいます。」です。