テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】AddressableAssetSystemで、他のプロジェクトのAASが作ったAssetBundleを利用する

f:id:tsubaki_t1:20190326225814j:plain

Addressableで他のプロジェクトが作成したAssetBundleを使用する方法についてです。

内容

  • AssetBundleを「上書き」する場合は、ContentCatalogを上書きするだけでいい
  • "AssetBundleに含まれるPrefab"が参照するスクリプトは利用する側に移植する
  • AssetBundleを「追加」する場合は、ContentCatalogをロードしてResourceLocationsに追加
  • Builtinshader assetbundleが重複する場合は、ビルドから外す

Addressableで他のプロジェクトが作成したAssetBundleを使用したい

他のプロジェクトのAddressableが作成したAssetBundleを 使用する というのであれば、実はそれ程難しくはありません。 ContentCatalogを他のプロジェクトが作った物に差し替えるだけです。

ただし、幾つか制限が追加されます。

  • Play Mode Script の Fast Mode や Virtual Mode は使用できない。
  • AssetReference系のAPIは使用できない

このあたりは完全にローカルにアセットが無いことが理由なので、仕方がないといえば仕方がないと言えます。

何にせよやってみようと思います。

なお今回はせっかくなので新しくリリースされたSDトーコちゃんズを使ってみました。Spring Boneが新型になり、ShaderもUTS2ベースになったので非常に良い感じです*1

f:id:tsubaki_t1:20190326230855p:plain

SDトーコちゃんズ登場! « UNITY-CHAN! OFFICIAL WEBSITE

Addressableのビルド用プロジェクトを用意する

今回は「ビルド用」と「実行用」のUnity Projectを用意します。どちらもAddressableは導入している状態です。

まずビルド用では、普通にAddressableを用意する環境を用意して Build Player Content します。

f:id:tsubaki_t1:20190326233600j:plain

ビルドした後は、以下の内容をexport packageしておきます。

  • StreamingAssets の中身・・・特に aaフォルダ 以下の内容
  • AssetBundleに含めたPrefabが使用しているscript全て

スクリプトはファイルのGUIDが同じ事、そしてハッシュが同じ(シリアライズ可能な設定が一致)なら、実装違っていても普通に使用できます。なので他のプロジェクト側でAssetBundleを使用したいならば、スクリプトも持っていく必要があります。

持っていくスクリプトはlink.xmlで確認するのが手っ取り早いです。

f:id:tsubaki_t1:20190326233216j:plain

【Unity】AddressableでAssetBundleをビルドすると link.xml も自動で生成される - テラシュールブログ

Addressableでビルド済みAssetBundleを使用する

次にビルド済みのAssetBundleを他のプロジェクトで使用します。

先程Exportした Unitypackageを「AssetBundleを利用するUnityProject」にインポートします。

重要なのは2つ。ContentCatalogデータと、catalogと同じパスにAssetBundleを配置することです。CatalogデータにABへのパス等が含まれるので、この2つさえ移植できれば概ね何とかなります。

あとは play mode scriptpack modeに設定すれば、他のAddressableが生成したAssetBundleを使用出来ます。

f:id:tsubaki_t1:20190326233952j:plain

public class LoadAddress : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Addressables.Instantiate("Toko_sum");
    }
}

f:id:tsubaki_t1:20190326234305j:plain

既存のAddressableを使いつつ、動的にカタログを追加する

既にローカルでAddressableを使用して云々している場合で、既存のプロジェクトに外部で作成したカタログを追加してみます。

例えば以下のような形でカタログを新しく追加出来ます。

using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Assertions;
using UnityEngine.ResourceManagement.AsyncOperations;

public class LoadAddress : MonoBehaviour
{
    IEnumerator Start()
    {
        // Webから新しいカタログを取得。ファイルパスかURL
        var requestCatalog = Addressables.LoadContentCatalog("http://192.168.100.100:51879/catalog_extra.json.json");
        yield return requestCatalog;
        Assert.AreEqual(AsyncOperationStatus.Succeeded, requestCatalog.Status);

        // カタログを追加
        Addressables.ResourceLocators.Add(requestCatalog.Result);

        // 新しいカタログ上のキャラクターを取得
        Addressables.Instantiate("Toko_sum");
    }
}

ただ、お互いに default shader保有しているためにAssetBundleがぶつかる事があるかもしれません。そういった場合は、ビルドスクリプトを少し書き換えてやります。

BuildScriptBase を継承したクラスを作成し、BuildScriptPackedModeの中身をほぼコピペで新しいビルドスクリプトを作ります。LinkXmlGeneratorなど一部internalがあったので Addressables System/Editorフォルダ以下に配置しました。

コードの変更点として、Built in shaderを作るタスクをビルドタスク一覧からコメントアウトで排除します。

f:id:tsubaki_t1:20190327003959j:plain

f:id:tsubaki_t1:20190327004345j:plain

ScriptableObjectを作成し、Data Buildersに登録、あとはBuild Scriptをカスタマイズした物に変更します。

f:id:tsubaki_t1:20190327004527j:plain

f:id:tsubaki_t1:20190327004643j:plain

これでローカルでは普通にAddressableを使用しつつ、外部で任意にカタログを追加して云々が出来ました。外部アセット(キャラクターや演出等)は外部でビルドしつつ、UIや幾つかのエフェクト等はローカルAddressableAssetSystemを使うとかすると良いかもしれません。

f:id:tsubaki_t1:20190327005239j:plain

f:id:tsubaki_t1:20190327005443j:plain

感想

AddressableはContentCatalogにアセットへのパスが含まれるので、コレをなんとかすれば割と素直に動いてくれます。 まだ未確認ですが、ContentCatalogをリロードしたい場合、一旦全てのアセット/インスタンスをリリースしてからコンテンツカタログを再ロードとかすると良いんじゃないかなと思ってます。変更チェックには.hash を使ってあげると良いかも。

ということで他のAASが使用したAssetBundleを使用してみましたが、Addressableは設計的には「全部のアセットを一つのプロジェクトに突っ込んで使う」「コンテンツ作成はFastモードで行い、CIでコンテンツ更新、動作確認は実機」だと思うので、ABを通さないと動作確認が出来なくなるモードは若干微妙な気分です。

関連

www.slideshare.net

www.slideshare.net

*1:インポート時にGUIDが変更されていなかったため、SD Unitychanが既にある場合はGUIDが重複して新しいSpringBoneが外れる現象が起こりました。