AssetBundle運用をなんとかするAutoya

# 概要
Unityのスマホ向けで実運用する上で必要なアセットバンドルのアレコレをちゃんと出来る（他の機能も色々入っている）オープンソースのフレームワークであるAutoyaがあります。
https://github.com/sassembla/Autoya

ドキュメント
https://sassembla.github.io/Autoya/


平和なプロジェクトのはずが、ある日突然アセットバンドル基盤周りを任せられたみたいなシチュエーションの人は、このAutoyaを使うと幸せになれると思います。


本記事はAutoya 0.8.40 を想定しています。
https://github.com/sassembla/Autoya/tree/0.8.40


一応手を動かす前に、アセットバンドル自体の説明として以下のエントリをお勧めします。

AssetBundleまったく分からない人向けのAssetBundleのメンタルモデル
https://qiita.com/neon-izm/items/b105130fac060ec40ad4

# Autoyaのアセットバンドル機能で何が出来るのか
公式のドキュメントにもありますが

- 認証を通したアセットバンドルのダウンロード
- アセットバンドル依存性の解決
- アセットバンドルに便宜上の独自バージョン情報を付けられる
- インターネット上、端末のローカルキャッシュ、メモリ上、の違いを意識せずに指定のアセットバンドルを活性化(Instanciate出来るようにする）出来る
- アセットバンドルのアップデートをサーバ参照して見つける（本体プログラム更新前にアセットバンドルだけダウンロードさせる）ロジック
- アセットバンドルダウンロード前にダウンロード予定サイズを取得してダイアログを出せる

などです。これらをちゃんと作るのは相当つらいので、Autoyaのシステムに乗っかると便利です。
preloadという用語がAutoyaのアセットバンドル関連で頻繁に使われますが、ダウンロードとほぼ同義だと覚えておくと理解が早いかもしれません。

AutoyaのAssetBundle機能はAssetGraphToolと一緒に使う事を前提にしているので

Autoya+AssetGraph.unitypackage を使うと良いと思います。

また、本家のドキュメントのアセットバンドルの項にも詳細な説明があるので、困ったら参照しましょう。
この記事は以下2個のドキュメントの補助みたいなつもりで書いています。

https://sassembla.github.io/Autoya/docs/en/assetbundle0.html
https://sassembla.github.io/Autoya/docs/en/resource_generate0.html

# Autoyaはいっぱいjsonファイルが使われていてよく分からない
最初にこれを説明します。いっぱいと言う割に3個しかない気がする。

//TODO:理解のために便宜的に名前を付けているのと、Autoya内で使われている名前に合わせる

### 1.アセットバンドル一覧json(AssetBundleLists)
https://github.com/sassembla/Autoya/blob/master/AssetBundles/main_assets/Windows/1.0.0/main_assets.json

アセットバンドルを組み込むときに、まずは「このプロジェクトの、このバージョンでビルドしたアセットバンドルの名前や、CRCや、依存性を網羅した一覧」が欲しいと思います。
一番情報量が多い、メインのjsonファイルですね。後述する様に、Autoyaはこのjsonファイルを**AssetGraphToolと連携してアセットバンドルビルド時に自動生成してくれます。**
凄くありがたい…
このjsonファイルをAutoya内部でサーバからダウンロードしてくれます。
こういう処理の内部でアセットバンドル一覧jsonファイルのダウンロード、更新が走っています。


```

        Autoya.AssetBundle_DownloadAssetBundleListsIfNeed(status => { }, (code, reason, autoyaStatus) => { });

        // wait downloading assetBundleList.
        while (!Autoya.AssetBundle_IsAssetBundleFeatureReady())
        {

            yield return null;
        }
```

### 2.preloadList用json
ゲーム開始後、全部のアセットバンドルを最初にダウンロードする、という運用ならここは読み飛ばして下さい。
最初にアセットバンドルを全部ダウンロードする場合のサンプルコードは
https://github.com/sassembla/Autoya/blob/master/Assets/AutoyaSample/2_AssetBundle/PreloadAssetBundle.cs
こちらです。

話を戻してpreloadリストとはなんぞやと言うと、
https://github.com/sassembla/Autoya/blob/master/AssetBundles/preload/sample.preloadList2.json
こういうjsonファイルです。リスト名と、アセットバンドル名だけが書いてあるjsonファイルです。

アセットバンドルを都度ダウンロードする運用で使います。つまり必要な時に必要な分だけアセットバンドルをダウンロードする運用の時に使うリストです。
ゲーム中に特定シーンに入る前に、このリストをサーバからダウンロードして（あるいはサーバからWebAPIでjsonを返して） 1.で説明したアセットバンドル一覧jsonと比較しながらダウンロードされていないアセットバンドルを見つけて端末に各アセットバンドルをダウンロードする。

と言う時に使います。 **手で書く、あるいはWebAPIを作る必要があります。**

### 3.アセットバンドル一覧jsonを作るためのjson
1.の全アセットバンドル一覧ファイルをAssetGraphToolから自動生成するためのメタデータです。
**将来的に自動生成されそうですが、現時点では手で生成する必要があります。**
詳細は [この項]( https://qiita.com/neon-izm/items/27326106738cee2fff69#%E3%83%93%E3%83%AB%E3%83%89%E3%81%97%E3%81%9F%E3%82%A2%E3%82%BB%E3%83%83%E3%83%88%E3%83%90%E3%83%B3%E3%83%89%E3%83%AB%E3%81%AE%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E5%85%88%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%A8%E8%A8%AD%E5%AE%9A)で説明しています。


# Autoyaセットアップ
Unity IAP(In App Purchase)を使う場合は
https://github.com/sassembla/Autoya/blob/master/README.md#installation

この通りです。しかしチーム開発でOrganizationを統一するのが難しいとか、別口の課金システムを使う場合は該当部分のスクリプトを消して　(https://github.com/sassembla/Autoya/tree/master/Assets/Autoya/Purchase 以下のディレクトリを消します)
OverridePoints.cs 内のPurchase周りのコードをコメントアウトすることで問題なく今回の用途に使うことが出来ます。

また、Unity5.x系で使う場合はAutoyaの最新版では無く
0.8.29 を使うようにしましょう（Cache周りのAPIとかの互換性が変わってます）
https://github.com/sassembla/Autoya/releases/tag/0.8.29

# 最初にアセットバンドルがビルド出来るかのテスト
アセットバンドルを配置するサーバURLや、アセットバンドルをビルドする出力先ディレクトリ周りの設定を最初に行う必要があります。

まずは上記セットアップが終わった時点で一旦コミットしてから、この設定変更をしていきましょう。
### アセットバンドルの一覧が書いてあるjsonリストをダウンロードする先のURL指定

こういうリストが後で自動生成されるので、アップロード先のサーバURLを指定しておきます。

https://raw.githubusercontent.com/sassembla/Autoya/master/AssetBundles/main_assets/Android/1.0.0/main_assets.json


Assets/Autoya/Settings/AutoyaRuntimeManifestObject.cs内の
public RuntimeManifestObject(){} の中に2.で後述するビルドしたアセットバンドル一覧を含んだjsonファイルダウンロード先のURLを書いておきます。
実際にAutoyaでリストURLとしてアクセスするのは

```
listDownloadUrl/listIdentity/platform/listversion/listIdentity.json 
```
になります。
つまり

```
 new AssetBundleListInfo
               {
                   listIdentity = "main_assets",
                   listVersion = "1.0.0",
                   listDownloadUrl = "https://raw.githubusercontent.com/sassembla/Autoya/master/AssetBundles"
               }
```

の場合は例えばAndroidなら、端末上から

```
https://raw.githubusercontent.com/sassembla/Autoya/master/AssetBundles/main_assets/Android/1.0.0/main_assets.json
```
にアクセスしてjsonファイルをダウンロードして、ダウンロードして端末に保存しているjsonファイルをアプリ内でパースする事でアセットバンドル一覧を取得することになります。

### ビルドしたアセットバンドルのエクスポート先ディレクトリの作成と設定
https://sassembla.github.io/Autoya/docs/en/resource_generate0.html
ここに書いてある作業です。上のURLを読んで分かれば問題ないです。

以下、念のための解説。
Autoyaに同梱されているAssetGraphToolでアセットバンドルをビルドすると、アセットバンドル一覧みたいなjsonファイルを生成してくれます。ちょうど上に書いた
https://raw.githubusercontent.com/sassembla/Autoya/master/AssetBundles/main_assets/Android/1.0.0/main_assets.json
こういうファイルです。

これを生成してくれるように、ちょっとした手作業を行う必要があります。

/Assets
/ProjectSettings
があるディレクトリに
/AssetBundle
というディレクトリを作ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/40627/5e03a1bc-b71b-3fec-01f4-703dcc6666b2.png)

このAssetBundleディレクトリの中に、AssetBundleListInfo でさっき書いたlistIdentityと同じ名前のjsonファイルを作成して、ファイルと同じ場所にlistIdentityと同じ名前のディレクトリを作成しておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/40627/ecb2b808-714a-396b-10cb-126087936f0b.png)
jsonファイルの中身は

```
{
    "identity": "unitychan_prefabs",
    "version": "1.0.0"
}
```
こういう感じの書き方をします。 **このjsonファイルだけ手で書いて下さい。** 
大事なことなので2回書きます。

**このjsonファイルだけ手で書いて下さい。** 

### アセットバンドルのビルドが動くか確認
AssetGraphTool用の設定ファイルを作成します。
お手軽に動作テストをするなら、インポートしたパッケージ内の
Assets/Editor/graphs/main_assets.asset をAssetGraphToolで開いてちょっと書き換えるだけでテスト出来ます。

1. LoadFromDirectoryのパスを変更(一個のプレハブだけがあるディレクトリを指定しておくと動作確認が楽)
2. Build Asset Bundles の **Force Rebuild Assetbundleチェックを入れる** (テスト中だけです）（余談ですが、書き換えじゃなくて新規でAssetGraph用の設定ファイルを作るなら、Build Asset BundlesのOutput Optionは **Build In Cache Directory**にしておきましょう）
3. Build AssetBundleから伸びているノードの先の Export To DirectoryのExport pathをさっき書いた /AssetBundle/listIdentity ディレクトリにしておきます。**このExport pathを指定する時に、指定したディレクトリにさっき手で書いたjsonファイルがあることを確認しておきましょう。**
4. Asset Graph Toolでビルドします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40627/e4f0553a-b233-348c-7b75-295153799aac.png)

Assetbundle以下のディレクトリにプラットフォーム名がついたディレクトリが出来ている事、プラットフォーム名ディレクトリの中にバージョン名のディレクトリが出来ている事を確認します。

更にバージョン名のディレクトリを掘ると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40627/cea831e1-407d-fb1f-7f03-4883d58569e0.png)
jsonファイルが出来ている事を確認します。
このjsonファイルの中身が、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/40627/5e77392f-b804-8215-35df-9ee660295f6c.png)

こんな感じでサイズやCRC、依存情報などが全部書かれていると思います。

バージョン名のディレクトリが出来ないとか、jsonファイルが見当たらない時は、本記事末尾のハマりと対応を確認して下さい。

### アセットバンドルのサーバへのアップロード
ゴソっとまるごとサーバに上げます。


# よくあるハマりと対応
## アセットバンドルがダウンロードじゃなくてキャッシュを参照してる気がする
以下の2個を実行して下さい。
1. persistent datapathの消去
Window→Autoya→ Persistence→Delete stored persistence
で全部チェック入れてdelete selected foldersを押す
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40627/f98cae83-ad2e-666f-11c5-d7a0de97b583.png)

2. Assetbundleのダウンロードキャッシュの消去
どうもキャッシュ周りが怪しいぞ、と思ったら、こういうスクリプトを貼り付けた空のシーンをエディタ上で実行→停止してみてください。

```cs
using AutoyaFramework;
using AutoyaFramework.AssetBundles;
using UnityEngine;
public class ClearAssetBundleDonwloadedCache : MonoBehaviour {
    void OnDestroy()
    {
        Autoya.AssetBundle_DeleteAllStorageCache();
    }
}

```

アセットバンドルダウンロードを実行している時だと、ダウンロードキャッシュの消去がOSのファイルロックで実行されない事があるので、**明示的に空のシーンで呼ぶことをお勧めします。**

また、エディタでコンパイルエラーを吐いたりすると、ファイルロックはクリア出来てもUnityEditorのメモリ上にアセットバンドルのキャッシュが残っていることがあります。(ClearCacheがfalseを返す)
もし不可解な症状があったら **UnityEditorを再起動** してください。


## ビルドしたアセットバンドルのエクスポート先ディレクトリのアセットバンドル群が更新されない
Autoya内部でエクスポート時にAssetBundleListInfoのバージョン情報を覚えているためです。
**PCのアセットバンドルエクスポート先ディレクトリの中身を都度削除する**か AssetBundleListInfoのバージョンを上げるかしてください。テストしてるだけなら前者がお勧めです。
**削除するのはAndroidとかWindowsとか書かれているフォルダからです。もっと上のディレクトリを消さないように**

## GitでpushするときにBuildManifest.json がコンフリクトする
複数人開発の時に Assets/Autoya/Manifest/ShouldGitIgnore/Resources/BuildManifest.json がコンフリクトすることが良くあります。これはAutoya内部で独自のビルド番号などを生成管理する機構で使うファイルです。
Assets/Autoya/Manifest/ShouldGitIgnore/ 以下をgitignoreしましょう。

## なんか全アセットバンドル一覧のjsonが出力されない気がする
AssetGraphのグラフ名、出力先ディレクトリ名、AssetBundleListInfoの名前あたりの一致、不一致を調べて下さい。

## アセットバンドルでprefabにAddComponentしたりしたい
**絶対に**InstanciateしてからAddComponentやGetComponent<>().hogeValue=fuga;みたいな処理をしてください。
Unity上ではInstanciateせずにキャストだけでAssetBundleを操作することが出来ますが、とんでもないバグを生む原因になるので止めましょう。Instanciateしてから触ってください。

# おまけ
実際にAutoyaのアセットバンドル機構を使ったサンプルプロジェクト
https://github.com/neon-izm/AssetBundleManager