UnrealEngine4のお勉強③DLC機能を実装する

UnrealEngine4で[MobilePatchUtility](https://docs.unrealengine.com/ja/Engine/Blueprints/UserGuide/PatchingNodes/index.html)を利用したDLC機能について書きます
この機能は自分の好きなタイミングで好きな単位のコンテンツをDLすることが可能です

なんか書き出したら、説明することたくさんあったので、2つか3つくらいに記事わけると思います
あ、DLCはDownload Contentsの略です（多分）

この記事では

- アプリとDLCの作成

について書いていきたいと思います。

[次の記事](https://qiita.com/kotarotaro_A/items/18051a4bde299cfd48e9)では

- ローカルサーバの準備とDL確認

について書きます。

自粛中のGWに暇すぎてなんとなく書いてるので、細かいとこまで確認してないので完璧な記事ではないと思いますがあしからず。
動くとこまでは確認しておきますので、緩い感じでお読みいただけると嬉しいっす。

※ちなみに、端末を準備するのがめんどくさいので、windowsアプリケーションで記事は書きますが、Android/iOSでも同様のことが可能です。
※ビルドコマンドが異なるだけなので、それも書いておきます。

## はじめに
DLCとはこんな感じです
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/78f6de60-4ac0-708e-310d-a671e4954071.png)
図にする意味がないくらい情報が書いてない図ですが、
例えば
ストアにあげるアプリにはチュートリアル終了までのデータだけ入れておく、
サーバにチュートリアル突破以降に必要なデータをあげておく、
そして、ユーザーがチュートリアルを突破したらサーバからデータをDLする
などのように使います。

## アプリとDLCの作成

### 作成するアプリの概要
アプリ内にレベルを1つ、DLCにレベルを2つ作成します
アプリからDLを実行して取得した2つのレベルを開けるようにします

### プロジェクト作成
UnrealEngineは今日時点の最新4.24.3を使います
プロジェクトの新規作成から、「ゲーム」→「Blank」を選択、
プロジェクト設定はブループリントをC++に変更してあとはそのまま。
てきとうにプロジェクト名(DlcSample)をつけてプロジェクトを作成します。
### DL実行レベルの作成
コンテンツディレクトリ直下に新規ディレクトリを作成します。
名前は「pak0」にでもしておきましょう。

そしてpak0の中に新規レベルを作成します。
名前は「LevelPak0」で。

プロジェクトの起動レベルをLevelPak0に変更しておきましょう。
上部バーの「編集」から、「プロジェクト設定」→「マップ&モード」→「デフォルトマップ」
ここの「エディタのスタートアップマップ」と「ゲームのデフォルトマップ」をLevelPak0に変更します。
それぞれエディタでの起動時に開くレベルと、ゲームでの起動時に開くレベルの設定です。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/4b281e69-0a3d-4083-687c-b521d3ecf696.png)


ではDLを実施するUIと処理を作成していきます。
pak0ディレクトリの中にウィジェットブループリントクラスを新規作成します
名前は「WBP_LevelPak0」です。（作り方は、pak0内を右クリック、「ユーザーインターフェース」→「ウィジェットブループリント」）

そして、作成したウィジェットブループリントを利用するための設定と、マウスカーソルを表示するための設定をします。
LevelPak0のレベルブループリントを開いて、BeginPlayからこんな感じで設定します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/eb4bdbc1-b06d-430f-b02f-b33b123451c2.png)

### DL処理の実装
DL処理の流れは

1. RequestContent
2. StartInstall
3. Mount

です。

必要な入力は

- Remote Manifest URL
- Cloud URL
- Install Directry

です。

なのでUIには3つのテキスト入力を受け付けるボックスとDL処理を実行するボタン、
そして、DLしたレベルに遷移するためのレベル名の入力を受け付けるボックスとレベル遷移を実行するボタン、
をそれぞれ配置します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/451d9ce7-0dac-cc6a-cbad-4ad13a22c7c8.png)
こんな感じ。
一番上のStatusはDL処理のStatusを簡易的に表示するためのテキストです。
これはなくてもいいですが、ないとDL処理が完了したのかを勘で判断する必要があります。

そしてDLの処理はこんな感じ
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/320cdb6d-0215-a134-6bfc-9238e2f786d4.png)
これは冒頭に貼ったリンクの処理そのままですので、そちらを参考に。

そしてレベル遷移の処理はこんな感じ
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/baf1d4af-dcdf-6df5-9dd6-d424d3379494.png)

これで処理部分は完成です。

### DLC作成用の設定
UE4ではDLCをpakという単位に分割して管理します。
2つのpakを作成して、それぞれの中にレベルを1つずつ含めるように設定していきます。

まず、コンテンツディレクトリ直下にpak1とpak2というディレクトリを新規作成します

pak1の中に「LevelPak1」、pak2の中に「LevelPak2」をそれぞれ作成します。

LevelPak1、LevelPak2はそれぞれ自分のレベル名がわかるテキストと、DL処理画面に戻るボタンを設置しておきましょう
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/07ecc1ea-9423-bdba-4aeb-3a9e71a77c6a.png)

処理はこんな感じ
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/237114f0-d94f-0d5e-fea8-0730a6def504.png)

そして、 **ここからが本題です。**
プロジェクト内の各コンテンツをどのpakに分けるのか設定するためには、PrimaryAssetLabelを利用します。
このラベルが割り振られたコンテンツは、このラベルの設定したpakに含まれることになります。

pak1とpak2ディレクトリにそれぞれPrimaryAssetLabel、PAL_1とPAL_2を作成します。
それぞれ作成したいディレクトリの中で、右クリック→「その他」→「データアセット」→「PrimaryAssetLabel」です。
そして設定はそれぞれこう。
PAL_1
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/2cfce9fd-3e70-dca4-349d-85d0aab54671.png)
PAL_2
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/8299fbb4-2b37-2ecd-4e3a-ae93eb14fc26.png)
最低限の説明だけします。（全部の説明はググれば出ます）

- Priority：PrimaryAssetLabelを重複して指定された場合に、どちらの設定を有効にするかの優先度です。<br>
ぶっちゃけ今回は重複してないので、設定いじる必要ないです。<br>
（ちなみにpak同士の親子関係の設定が存在して、重複の優先度を真剣にやるならそちらについても調査してから実装することをおすすめします）
- Chunk ID：これがpakを分ける設定になります。ChunkID=1はpakchunk1.pak、ChunkID=2はpakchunk2.pakというpakに振り分けられ、アプリには含まれません。<br>
デフォルトはChunkID=0となりpakchunk0.pakはアプリ内に含まれます。
- Label Assets in My Directory：ここにチェックを入れると、このラベルが存在するディレクトリ以下のコンテンツはすべてこのラベルの設定が有効になります。
- Explicit Assets：個別にこのラベルに設定したいコンテンツはここに入れます。
- Explicit Blueprinbts：個別にこのラベルに設定したいBlueprintはここに入れます。

要するにこのプロジェクトでは、
pak1ディレクトリ以下のコンテンツはすべて、pakchunk1.pakの中に、
pak2ディレクトリ以下のコンテンツはすべて、pakchunk2.pakの中に含まれることになります。
そしてPrimaryAssetLabelが設定されていない、pak0ディレクトリ及びその他のコンテンツたちは、pakchunk0.pakの中に含まれ、アプリ内に入ります。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/3ec7e53d-5a9b-008b-cd24-dcafd26df812.png)
こんな感じ。

### ビルド
プロジェクトは完成したのでビルドしていきます。
その前にプロジェクト設定を追加しておきます。
上部バーの「編集」→「プロジェクト設定」→「パッケージ化」→「Packaging」の設定をこんな感じにしてください
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212804/7633e6af-815d-6945-37d2-07294349e77e.png)
HttpチャンクインストールディレクトリはDLCのビルド結果の出力場所なので、任意の場所に書き換えてください。

設定完了したらビルドします。
同じく上部バーの「ファイル」→「プロジェクトをパッケージ化」→「Windows」→「Windows(64bit)」を選択
（32bitの方はそちらをどうぞ）
アプリのビルド結果の出力先を聞かれますので、これも任意の場所を指定してください。

ちなみにコマンドビルドの場合はこんな感じ

```bat:build.bat
call "[UE_4.24までのパス]\Engine\Build\BatchFiles\RunUAT.bat" ^
-ScriptsForProject=[プロジェクトまでのパス]/DlcSample.uproject ^
BuildCookRun ^
-nocompile ^
-nocompileeditor ^
-installed ^
-nop4 ^
-project=[プロジェクトまでのパス]/DlcSample.uproject ^
-cook ^
-stage ^
-archive ^
-archivedirectory=[アプリ出力先のパス] ^
-package ^
-ue4exe="[UE_4.24までのパス]\Engine\Binaries\Win64\UE4Editor-Cmd.exe" ^
-pak ^
-prereqs ^
-nodebuginfo ^
-manifests ^
-targetplatform=Win64 ^
-build ^
-manifests ^
-createchunkinstall ^
-chunkinstalldirectory=[DLC出力先のパス] ^
-chunkinstallversion=1 ^
-target=DlcSample ^
-clientconfig=Development ^
-utf8output
```

Androidの場合、
-targetplatform=Win64 を -targetplatform=Android に変更。
-cookflavor=[テクスチャの圧縮形式名(ASTCとか)] を追加。

iOSの場合
-targetplatform=Win64 を -targetplatform=iOS に変更。

これでそれぞれビルドできるはずです。
（多分-prereqsはいらないかも）
（UE4の設定でそれぞれのビルドに必要な設定は追加しておいてください。）

このコマンドで実行する場合は、
プロジェクト設定で追加した「チャンクの生成」や「Httpチャンクインストールデータのビルド」の設定は不要です。
（コマンドに書いてあるから）

### ビルド結果の確認
アプリの出力先に指定したディレクトリの中に
WindowsNoEditor\DlcSample\Content\Paks\pakchunk0-WindowsNoEditor.pakが存在し、
DLCの出力先に指定したディレクトリの中に
WindowsNoEditor\1\pakchunk1\pakchunk1-WindowsNoEditor.pak
WindowsNoEditor\1\pakchunk2\pakchunk2-WindowsNoEditor.pak
この2つが存在していれば正しくビルドできています。

では、DlcSample.exeを起動して、
OpenLevelのテキストボックスの中に「LevelPak1」と入力して、OpenLevelボタンを押下します。
**レベルが遷移しないことを確認します。**

アプリの中にはpak0しか入っていないので、LevelPak1とLevelPak2には現時点で遷移することができません。

サーバに配置してDLしてレベル遷移できることの確認は[次回の記事](https://qiita.com/kotarotaro_A/items/18051a4bde299cfd48e9)に書きますので、
続きはそちらでお願いします。

### DLしないで確認する方法
DLCビルド出力ディレクトリにある
WindowsNoEditor\1\pakchunk1\pakchunk1-WindowsNoEditor.pak
WindowsNoEditor\1\pakchunk2\pakchunk2-WindowsNoEditor.pak
この2つのpakファイルを
アプリビルド出力ディレクトリの
WindowsNoEditor\DlcSample\Content\Paks
ここにコピーしてから、exeを起動します。
すると「LevelPak1」と「LevelPak2」に遷移できますのでご確認ください。

終わり。