【Unity】リソースを適切に管理しよう

45.1K Views

April 14, 23

スライド概要

2021年10月に銀座Unityもくもく会でLTした資料です。

profile-image

フリーランスのTAです。 主にもくもく会でのLT資料などをアップロードしたいと思います。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

(ダウンロード不可)

関連スライド

各ページのテキスト
1.

リソースを適切に管理しよう おかひろ

2.

自己紹介  おかひろ  Twitter:@okahiro_p  フリーランスのゲームプログラマー   ソシャゲ4年半、ハイパーカジュアル半年  最近はHoudiniを勉強している 東方放置譚、東方地風陰、東方弾闘戯というゲームをリリース

3.

はじめに ※素材:ゆるドラシル RPGツクール 素材提供サイト (yurudora.com)  こんな感じのキャライラストをゲームに使いたい  キャラの数は数十体(アップデートで増える予定あり)  キャライラストは綺麗に見せたいので、解像度高くしたい

4.

画像一つの容量  1385x2048で約11MB  実際はこんなに大きく使うことは少ないと思う が、後の検証がわかりやすいようにわざと大き くしておく。

5.

作成する画面の仕様  左上の“LoadChara”ボタンを押したらキャライ ラストを画面に表示する(今回はランダムに した)  キャライラストが二枚同時に表示されること はない(切り替えたら、前のイラストは不 要)

6.

Unityでの実装方法  SceneのGameObjectにアタッチ、もしくはそれにアタッチされている ScriptableObjectなどにアタッチ  Resources.Load  AssetBundle/Addressables

7.

SceneのGameObjectにアタッチ ここに全キャラのイラスト (今回は20枚)をアタッチ!

8.

SceneのGameObjectにアタッチ Sceneに遷移した瞬間に、20 キャラ分(約220MB)のメモリが 確保されている!! (キャラを表示していなくてもメ モリ上にのっかる) キャラが100体いたら1GB以 上!!! 恐ろしい・・・ また、Sceneの最初の読み込みに 時間がかかる。 EssentialPhone(PT-1)で750ms程度。 (キャラ20体のとき) ※実機Profileの結果です

9.

SceneのGameObjectにアタッチ  SceneのGameObjectに直接アタッチでなく例えばSceneにはScriptableObject がアタッチされていて、リソースがそのScriptableObjectにアタッチされてい ても結果は同じ  リソースがPrefabにアタッチされていて、SceneにはPrefabがアタッチされて いる形でも結果は同じ  Sceneがロードされるときに一気にメモリに展開されるので、Scene遷移も重い  別のSceneに遷移すると、アタッチされている分のメモリは解放される

10.

Resources.Load Resourcesフォルダにキャラのイラストを入れておく (Assetsの下であれば階層はどこでもよい)

11.

Resources.Load Sceneロード直後(まだイラストはLoadしていない) はイラストのメモリは確保されていない イラストをロードしたら、該当のイラストの分だけメ モリ確保された イラストを切り替えたら、読み込んだ分のメモリが確 保されている。 (画面に表示されているイラストは1枚のみ) Resources.UnloadUnusedAssets を実行すると、現在表 示されている(使われている)イラスト以外のメモリ は解放される

12.

Resources.Load  メモリ確保についてはある程度適切に行われていそう   Resourcesフォルダに入っているファイルが多くなると、アプリの起動に時間 がかかるようになる   適切な箇所でResources.UnloadUnusedAssetsは推奨 内部的に索引のようなものを作っていると思われる そもそもUnityが公式で推奨していない  https://learn.unity.com/tutorial/assets-resources-andassetbundles#5c7f8528edbc2a002053b5a7

13.

AssetBundle AssetBundleをビルドしておき、StreamingAssetsに格納し ておく。 ※同じファイル名のファイルのひとつはAssetBundle、も うひとつはmanifestファイル。

14.

AssetBundle Sceneロード直後(まだイラストはLoadしていない) はイラストのメモリは確保されていない イラストをロードしたら、該当のイラストの分だけメ モリ確保された イラストを切り替えたら、読み込んだ分のメモリが確 保されている。 (画面に表示されているイラストは1枚のみ) AssetBundle.Unload(true)を実行するとメモリは解放 される。 現在表示しているイラストでもUnloadすれば解放され、 画面上のイラストも消える。 初期化(Manifest読み込みなど)処理112ms、読み込み処理時間は60~90ms程度 (暗号化なし。LZ4圧縮) EssentialPhone PH-1で測定

15.

AssetBundle  メモリ管理をきちんと行うことができる  適切な場所でAssetBundle.Unloadを呼ぶ必要がある    使い終わったからといって勝手には解放されない AssetBundleはビルドする必要がある  プラットフォームごとにビルドが別  対象アセットに更新があったら、またビルドが必要 AssetBundleのAPIを呼ぶ処理を結構自前で用意しないといけない  AssetBundleのビルドを行うEditor拡張  AssetBundleの依存関係を取得/解決  CDNからダウンロードしたAssetBundleをローカルキャッシュする

16.

Addressables

17.

Addressables BundleModeを“Pack Together”にすると、Groupごとにファイルがまとめられる。 読み込み処理時間は初回(小さなファイル読み込み)が910ms、 それ以降初回が1420ms、以降は40~70ms程度(暗号化なし。LZ4圧縮) EssentialPhone PH-1で測定

18.

Addressables BundleModeを“Pack Separetely”にすると、Assetごとにファイルが分かれる。 読み込み処理時間は初回(小さなファイル読み込み)が1200ms、 次回以降は150-170ms程度(暗号化なし。LZ4圧縮) EssentialPhone PH-1で測定

19.

AddressablesのBunldeMode別読み込み時間  本命の画像ファイルの前に、小さなファイルを一度読み込んでおく  初回のロード時にCatalog読み込みなど含めた初期化を行っている?    大体1000msぐらいかかった(EssentialPhone PH-1で測定) Pack Together Pack Separately 1回目の画像読み込み 1400ms 150-170ms 2回目以降の画像読み込み 40-70ms 150-170ms PackTogetherは初回で30MBのファイルをロードしているか、1回目だけ時間がかかる。  ロードしたファイルに含まれている別の画像をロードするのは早い。  すべてReleaseすると、もう一回30MBファイルロードしている模様  PackTogetherでロードしても、Profilerでは読み込んだファイルのみメモリに乗っているように 見えた PackSeparatelyは画像ごとにファイルが別れているため初回に時間がかかるというのはないが、 2回目以降も速度は変わらず、Togetherよりも時間がかかっている。

20.

Addressables  メモリ管理をきちんと行うことができる  適切な場所でAddressables.Releaseを呼ぶ必要がある    Addressablesはビルドする必要がある  プラットフォームごとにビルドが別  対象アセットに更新があったら、またビルドが必要  アプリのビルド前に自動的にAddressablesビルドを行うスクリプトを挟んでおくと 便利 AssetBundleと違い、自前で用意しなくてはいけない処理はあまりない   使い終わったからといって勝手には解放されない 大体用意してくれている 暗号化とか独自キャッシュを使おうとすると、カスタマイズが必要

21.

AssetBundle/Addressablesの分け方  複数のAddressablesが別の同じリソースをアタッチしている場合 4つのAddressables アセットが同じ Spriteをアタッチし ている

22.

AssetBundle/Addressablesの分け方 ビルドしたファイルは、4つそれぞれにSpriteが含まれる →本来のSpriteは1個だけなのに、容量は4倍になっている それぞれのAddressableアセットをロードすると、もとのSpriteは同じなのに 別Spriteとしてメモリを確保してしまう

23.

AssetBundle/Addressablesの分け方 この場合、ScriptableObject(Addressables)がアタッチしているSpriteもAddressables に登録する。 こうすると、ビルドしたときにSpriteがそれぞれの中に含まれず、独立した Addressablesアセットになる。 ScriptableObject側からは依存関係がある扱いになり、 ScriptableObjectがロードされるとSpriteも依存関係が解決されて一緒ロードされる。

24.

AssetBundle/Addressablesの分け方 Chara20.pngのAddressablesアセットが別になり、ScriptableObject側の容量は減った。 Profilerで該当のすべてのScriptableObjectをロードしても、Spriteはひとつな のでメモリも一つ分の確保になった。

25.

まとめ  たくさんのリソースを使う場合、使い方や量、種類などをきちんと把握し、適切な 管理方法を選択する必要がある。    Inspectorにアタッチ  一番楽  量が多くなるとSceneのロード時間が増え、メモリ展開量も増える Resources.Load  楽  量が多くなるとアプリ起動時間が増える  Unity公式で非推奨 AssetBundle/Addressables  習得の壁が高い  ビルド  非同期ロード  解放  ロード時間やメモリ確保量を制御できる  大きなプロジェクトではほぼ必須

26.

ご清聴ありがとうございました