ambrにAddressable Assetsを導入してアイテムを外部からロードしてみた

![logo.png](https://qiita-image-store.s3.amazonaws.com/0/304897/670b0b8a-cdb3-d22c-a990-d3af26e71c4b.png)

# はじめに
ambrにおいて、Addressable Assetsを導入する試みを行いました。
今回の記事ではざっくりとAddressable Assetsの設定の手順に関してご説明していこうと思います！
## ambrとは
ambrとは新しい仮想世界の実現を目指すVRソーシャルサービスです。
誰でも手軽に好きなアバターに変身してコミュニケーションを楽しむことができます。
対応プラットフォームは現在のところOculus Goのみですが、将来的にはVRデバイス全てに対応したマルチプラットフォームアプリを目指しています！
近々リリース予定ですのでよろしくお願いします！
Twitterで情報発信しておりますのでよろしければフォローをお願いします！
<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">I&#39;m tweeting from <a href="https://twitter.com/hashtag/ambr?src=hash&amp;ref_src=twsrc%5Etfw">#ambr</a> <a href="https://t.co/V3EUR7IWc5">pic.twitter.com/V3EUR7IWc5</a></p>&mdash; tanaco VR | ambr VPoE (@tanacooo) <a href="https://twitter.com/tanacooo/status/1076092506218160128?ref_src=twsrc%5Etfw">2018年12月21日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 環境
* Unity 2018.2.12f1
* Addressables 0.4.6-preview

## ambrにおけるアイテムとは
ambrにはアイテムを使用する機能があります。イベント等で取得したアイテムを好きなときに使用し楽しむことができます。
こんなふうに
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3330343839372f30383930313961662d306238362d663961642d656133652d3161383564303264646264382e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/304897/c25107b8-4dd1-e4f3-e609-3ede961fccf1.png)


これは水鉄砲をアバターが装備するアイテムですね。ベータ版ではPvEイベントの際にこの水鉄砲を使って敵にダメージを与えました。
このアイテムのモデルデータを外部サーバからAddressable Assetsを使って読み込んでいます。

## なぜAddressable Assetsを採択したのか
今後、アイテムのモデルデータ等が格段に大きくなることが予想されるため、AssetBundleで外部データ化することは決定していました。
最近Unityに追加されたAddressable Assetsがアセット間の依存解決やバージョン管理、キャッシュなど
AssetBundleでハイコストな問題へのサポートが強力だったため、まだPreview版ですが採用することにしました。

# Addressable Assets設定の手順

## Package Managerの設定
Addressable AssetsはUnity Package Managerを使用して導入することができます。
Packages/manifest.jsonに以下のように追記します。

```json:Packages/manifest.json
{
  "dependencies": {
    "com.unity.addressables": "0.4.6-preview"
    }
}
```
こうすることでPackge ManagerにAddressable Assetsが表示され、使用することができます。

## アセット登録 ＆ ビルド

Window -> Asset Management -> Addressable Assetsで管理用のWindowを開き、Create Addressables SettingsをクリックするとAssets/AddressableAssetsData以下に設定ファイルが作成されます。
その後、Addressable Windowに登録したいアセットまたはPrefabをD&Dし、ビルドすることで、Addressableインスペクタから設定できるBuild Pathにアセットバンドルが生成されます。
このときAsset Address欄がコードから呼び出すAsset名になりますが、デフォルトでフルパスが設定されて非常に長くなりますので
右クリック→Simplify Entry Namesするとファイル名まで短縮されるので使い勝手が良くなると思います。
この時Asset名の重複を起こしてはいけないので気をつけましょう。
![Unity 2018.2.12f1 Personal (64bit) - [PREVIEW PACKAGES IN USE] - ManagerScene.unity - projecttwins - Android_ _OpenGL ES 3.1 AEP_ 2019-01-09 10.44.57.png](https://qiita-image-store.s3.amazonaws.com/0/304897/7eae1aeb-6813-5248-9cc9-92cbe2765a57.png)



## ロード
生成したアセットバンドルファイル群を自前で用意したサーバにアップロードします。
ambrではAWSのS3を使用しています。
最後に、サーバの格納パスをAddressable インスペクタのLoad Pathに設定すれば設定完了です。
![Unity 2018.2.12f1 Personal (64bit) - [PREVIEW PACKAGES IN USE] - ManagerScene.unity - projecttwins - Android_ _OpenGL ES 3.1 AEP_ 2019-01-09 10.54.45.png](https://qiita-image-store.s3.amazonaws.com/0/304897/03f35699-e3a3-e717-f8e4-91b5d5e800d9.png)

コード側は、LoadAssetに読み込みたいAssetのパスの文字列を渡すことでロードできます。

```C#
Addressables.LoadAsset<GameObject>("Asset/xxxx")
```

アセット名をハードコーディングしたくない場合は、AssetReferenceをインスペクタに露出させて、Addressable WindowからD&Dでアタッチすると
LoadAsset()の引数に渡すことができます。
![Unity 2018.2.12f1 Personal (64bit) - [PREVIEW PACKAGES IN USE] - ManagerScene.unity - projecttwins - Android_ _OpenGL ES 3.1 AEP_ 2019-01-10 17.38.13.png](https://qiita-image-store.s3.amazonaws.com/0/304897/1173de53-83ba-c623-6e44-f47041011d59.png)

AddressableがPrefabである場合、以下のように実体化することができます。

```C#
public AssetReference hogePrefabRef;

Addressables.LoadAsset<GameObject>(hogePrefabRef)
.Completed += (op) =>
{
   GameObject go = Instantiate(op.Result);
   HogeClass hoge = go.GetComponent<HogeClass>();

   //初期化処理
};
```

※注意
[AssetReferenceTypeRestriction(typeof(HogeClass))]
public AssetReference hogePrefabRef;
AssetReferenceのインスペクタ露出時に、上記のように属性をつけると型指定ができる…はずですが、0.4.6環境下ではうまく動きませんでした。

Prefabの場合、LoadAssetの型指定でPrefabにアタッチされているクラスの型が指定できそうですが、
0.4.6環境下ではエラーが出てしまいますので、生成後にGetComponentしています。
今後のAddressableのアップデートで解消されるかも？

# 最後に
ambrでは可能な限り新しい技術に取り組み、エンジニアチームの技術力向上にチャレンジしています。
しかし、よりよいサービス開発を行っていくためにはまだまだ人手や知識が不足しています。
そんなambrに手を貸していただけるエンジニアの方を絶賛募集中です！
もし、興味のある方がいらっしゃれば、下記のBosyuや、TwitterのDMでご連絡ください！

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">リリース版の開発に向け、本格的にUnityエンジニアの募集を開始します！<br>これからのambrを支える重要なポジションを担当してもらうことになりますので、チャレンジングなお仕事になると思います！<br><br>新しい仮想世界&quot;ambr&quot;を一緒に創ってくれるUnityエンジニア募集！<br> <a href="https://t.co/Udp32olg6R">https://t.co/Udp32olg6R</a> <a href="https://twitter.com/hashtag/bosyu?src=hash&amp;ref_src=twsrc%5Etfw">#bosyu</a></p>&mdash; tanaco VR | ambr VPoE (@tanacooo) <a href="https://twitter.com/tanacooo/status/1072049613979316226?ref_src=twsrc%5Etfw">2018年12月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>