LoginSignup
21
14

More than 3 years have passed since last update.

簡単リモートアセット(Unity Addressable Asset System)を試してみた (その1)

Last updated at Posted at 2019-08-30

前提

公式ドキュメント

導入

  • パッケージマネージャーを使ってAddressablesを導入します。
  • Window (Menu) > Package Manager > Pakkages (Window) > Addressables > Install (Button) SS-13.png

Addressablesの初期化

  • Addressablesウィンドウで初期化を実施します。
  • Window (Menu) > Asset Management > Addressables (*) > Addressables (Window) > Create Addressables Settings (Button)
    ※ 1.3.8だと、Groups SS-1.png

設定

  • Addressables (Groups)ウィンドウから設定を選び、インスペクターで設定します。 SS-2.png
  • Addressables (Window*) > Profiles Default > Inspect Profile Settings
    ※ 1.3.8だと、Addressables Groups (Window)
    SS-3.png

カタログ

  • Player Version Overrideを記入し、Build Remote Catalogをチェックして、Remote Catalog Build/Load PathをRemote Pathに設定します。
    SS-4.png
    これで、指定したバージョンを含む名前で、Build Pathにカタログが生成されます。
  • バージョンが指定されないと、代わりにビルド日時が使われます。
    古いカタログは自動的に削除されないので、ファイルが増えていきます。
    対して、同じバージョンを指定している間は、カタログは上書きされます。
  • カタログは、実行時にリモートから読み込まれ、ローカルと比較して更新の有無が判定されます。
    カタログが作られていなかったり、正しいカタログが読み込めないと、アセットファイルが新しくなっていても更新は行われません。
  • アプリとアセットが必ず同時に更新されるプロジェクトであれば、カタログは不要だと思われます。
    対して、アセットだけ更新される場合は、カタログが必要です。

リモートパス

  • RemoteBuildPathRemoteLoadPathを記入します。
    SS-7.png
  • これらは、それぞれ、「アップロードするアセットファイルを作るフォルダ」と「アップロード先(=実行時に取得する)のURL」です。
    • [BuildTarget]が、ビルドターゲットを表す文字列に置き換えられることで、ターゲット毎に異なるアセットに切り替わります。
    • アップロード先へは、自分でアップロードする必要があります。

ラベル

  • 新しいラベル(タグ)を作ります。
    SS-5.png
    SS-6.png
    これによって、ラベル毎に一括ロードできるようになります。

アセットの構築

グループの作成

  • Addressablesウィンドウにグループを作ります。
  • Addressables (Window*) > Create New Group (Context Menu) > Packed Assets
    ※ 1.3.8だと、Addressables Groups (Window) SS-8.png
  • デフォルトグループは、コンテキストメニューから切り替え可能です。

グループの設定

  • Addressablesウィンドウで作成したグループPacked Assetsを選択して、インスペクターで設定します。
  • Build PathLoad Pathをリモートに設定します。
    SS-9.png

アセットの追加

  • グループにプロジェクトウインドウからアセット(ファイルまたはフォルダ)をドラッグ&ドロップして追加します。
  • フォルダを追加すると階層ができます。
    SS-10.png
  • Addressablesに追加されたアセットには、マークが付きます。
    SS-13.png
    • このチェックを外すと、Addressablesウィンドウからも消えます。
  • 逆に、Projectウィンドウで選んだアセットに対して、インスペクターでマークすることで、デフォルトグループに加えることも可能です。
  • アセットや階層には、ラベル(タグ)を付けられます。
    SS-11.png
  • アセットや階層の名前(Asset Address)は元のパス名から自動で付けられます。
  • これらのアドレスは任意に変更できます。アセットや階層を選んで、コンテキストメニューからSimplify Entry Namesを実行すると自動的に短くできます。
    SS-12.png
  • アセットや階層の名前は、Addressablesウィンドウでも、インスペクターでも変更可能です。
  • アセットや階層は、ドラッグ&ドロップで、あるいは、コンテキストメニューからグループ間を移動できます。

アセット(だけ)のビルド

  • Addressables (Window) > Build > Build Player Content

アセットを使う

アセットの参照

  • アセットは、string(名前、ラベル)、または、AssetReference(インスペクター経由)で特定します。
// インスペクターでアセットを指定する
[SerializeField] private AssetReference SpriteAsset = default;
  • 以降の例では、AssetReferenceは使用せず、名前とラベルを使います。

サンプルの流れ

SampleMain.cs
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AddressableAssets;

public class SampleMain : MonoBehaviour {

    private void Start () {
        StartCoroutine (loader ());
    }

    private IEnumerator loader () {
        // ロードの開始
        var textHandle = Addressables.LoadAssetAsync<GameObject> ("Prefabs/BottomText.prefab");
        var imageHandle = Addressables.LoadAssetAsync<GameObject> ("Prefabs/FullScreenImage.prefab");
        var spriteHandle = Addressables.LoadAssetsAsync<Sprite> ("Sprites", null); // ラベルを指定して一括ロード
        // 完了の待機
        yield return new WaitUntil (() => textHandle.IsDone && imageHandle.IsDone && spriteHandle.IsDone);
        // エラーがないことを確認
        if (textHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded
            && imageHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded
            && spriteHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded) {
            // プレファブからオブジェクトを生成
            var image = Instantiate (imageHandle.Result, transform).GetComponent<Image> ();
            var text = Instantiate (textHandle.Result, transform).GetComponent<Text> ();
            // スプライトを順に切り替え
            for (var i = 0; i < spriteHandle.Result.Count; i = (i + 1) % spriteHandle.Result.Count) {
                image.sprite = spriteHandle.Result [i];
                text.text = $"{spriteHandle.Result [i].name}  <size=20>© UTJ/UCL</size>";
                yield return new WaitForSeconds (3f);
            }
        }

    }
}

  • 非同期に処理する必要があるので、コルーチンを使います。
  • プレハブは個別の名前を、スプライトは一括してラベルを指定してロードを開始します。
  • 非同期ロードハンドルをチェックしてロードの完了を待ちます。
  • ロードが成功したかチェックします。
  • プレハブからオブジェクトを生成します。
  • スプライトを順に表示します。

プロジェクトの入手 (GitHub)

ダウンロード ⇒ AddressableAssetsTest.unitypackage
ソースはこちらです。

追補 (1.2.4)

  • 先祖-子孫関係のフォルダーを双方Addressablesに加えると、ビルド時に重複エラーが生じます。しかし、エディターで実行する際には、このエラーは検出されません。
    • 所在の異なる同じ名前のフォルダーをAddressablesに加えることは可能です。
  • Addressablesに加えたアセットの名前や所在を変更した際に、まれにAddressablesが追従することがあります。しかし、たいていはそのままなので、再度加え直す必要があります。

追補 (2020/04/04)

  • Unityエディタ上では動くのに、スマホ実機(iOS/Android)で例外が発生して止まってしまうことがあります。
    • Xcodeのログで 「MissingMethodException: Default constructor not found for type UnityEngine.ResourceManagement.AsyncOperations.ProviderOperation」とか出ます。
    • まず、アドレスの不整合を疑ってみましょう。
      • "Simplify Addressable Names"を前提にしたコードなのに、"AddressablesAssets Groups"ウインドウで実施を忘れているとかないでしょうか?

あとがき

気になったこと

  • まだ、公式ドキュメントが英語しかないようです。
  • 短期間に色々変わっているようで、ネットで調べた情報が実際と異なったりしました。
  • 設定をいじっていたら、Addressablesウインドウからアセットの一部が消えてしまって復旧できなくなる…ということが2度ありました。

今後の予定

  • 次回は「Addressablesを製品で使うとどうなるだろう」というテーマになると思います。
  • 具体的な製品プロジェクトの予定が立ったら進展すると思います。

参考にさせていただいた記事 (Qiita)

どうもありがとうございました。


UNITY-CHAN! © Unity Technologies Japan/UCL

21
14
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
14