【ITニュース解説】[Unity] Addressables使用時のロード時間やメモリ消費量
2025年09月27日に「Qiita」が公開したITニュース「[Unity] Addressables使用時のロード時間やメモリ消費量」について初心者にもわかりやすく解説しています。
ITニュース概要
UnityのAddressables機能が、ゲームのコンテンツを読み込む速度や使うメモリ量にどう影響するかを検証。PCやコンソール向けに、その挙動を詳しく調査した結果をまとめている。
ITニュース解説
Unityでゲームやアプリケーションを開発する際、キャラクターのモデル、背景画像、効果音といった様々な素材、これらを「アセット」と呼ぶ。これらのアセットを適切に管理し、必要な時に効率よく読み込み、不要になったらメモリから解放することは、アプリケーションの動作速度や安定性を保つ上で非常に重要だ。特に、多くの高品質なアセットを使用する大規模なプロジェクトでは、その重要性はさらに増す。Unityには、このアセット管理をより柔軟かつ効率的に行うための「Addressables(アドレッサブルズ)」というシステムが用意されている。これは、どのアセットをいつ、どこから読み込むかを開発者が細かく制御できる仕組みで、アプリケーションの初回ダウンロードサイズを抑えたり、パッチ配信を容易にしたりといったメリットがある。しかし、その内部的な挙動、特にアセットの読み込み(ロード)にかかる時間や、メモリの使用量(メモリ消費量)が具体的にどのように変化するのか、詳細な理解なしに使い始める開発者も少なくない。
今回の検証では、AddressablesをUnityプロジェクトで使用した際のアセットのロード時間とメモリ消費量について、その具体的な挙動を明らかにすることを目的としている。使用環境はUnity 6.2とAddressables 2.7.3、そしてWindows DevelopmentBuildで、実際の開発に近い状況を想定している。この検証を通じて、Addressablesの適切な使い方や、プロジェクトのパフォーマンスを最適化するためのヒントを探る。
まず、画像データである8Kテクスチャ3枚と、スクリプトで生成したメッシュを対象に検証を行った。これらのアセットをAddressablesのグループに登録し、Addressables.LoadAssetAsyncという命令で非同期にロードする。Addressablesのグループには「ローカルグループ」と「リモートグループ」の二種類がある。ローカルグループのアセットは、アプリケーション本体と一緒にビルドされ、ユーザーのデバイスにインストールされる。一方、リモートグループのアセットは、アプリケーションとは別にサーバーに配置され、必要に応じてインターネット経由でダウンロードされる。
検証の結果、アセットの初回ロードにはある程度の時間がかかることが確認された。これは、Addressablesが内部的にアセットのカタログ情報(どのアセットがどこにあるかを示すリスト)を読み込む必要があるためだ。しかし、一度ロードされたアセットは内部的にキャッシュされるため、2回目以降のロードは格段に速くなる。メモリ消費量については、ロードしたアセットのデータサイズに応じて増加する。これは当然の挙動だが、重要なのは不要になったアセットをどのように解放するかだ。Addressables.Releaseという命令を使うと、アセットへの参照が解除され、メモリ解放の準備が整う。ただし、実際にメモリが解放されるのは、そのアセットを参照しているものが一切なくなった時だ。もし複数の箇所から同じアセットを参照している場合、全てのリファレンスが解除されるまでメモリは解放されない。必要であれば、Resources.UnloadUnusedAssetsとGC.Collectという命令を組み合わせることで、強制的に不要なアセットをメモリから解放できる場合もある。リモートグループのアセットの場合、初回ロード時にはダウンロード時間も加わるため、ローカルアセットよりもさらに時間がかかるが、これも一度ダウンロードされればキャッシュされるため、2回目以降は速くなる。
次に、ゲームの画面そのものを構成する「シーン」をAddressablesで管理した場合の挙動を検証した。Addressables.LoadSceneAsync命令でシーンをロードすると、そのシーンに含まれるアセット(モデル、テクスチャ、マテリアルなど)も同時にロードされるため、メモリ消費量は大きく増加する。シーンの初回ロードもアセットと同様に時間がかかるが、これもキャッシュにより2回目以降は速くなる。注意すべき点として、シーンをアンロードしても、そのシーンが参照していたすべてのアセットが自動的にメモリから解放されるわけではない。特に、シーン内で使用されていたアセットが他の場所からも参照されていたり、Addressablesの内部的な参照が残っていたりする場合、メモリに残ってしまうことがある。ここでも、不要なアセットを確実に解放するためには、Addressables.Releaseを適切に呼び出すか、Resources.UnloadUnusedAssetsとGC.Collectを併用するなどの追加の対応が必要になる場合がある。
アセット間には依存関係が存在することがよくある。例えば、3Dモデルの見た目を決める「マテリアル」が、その見た目を構成する「テクスチャ」を参照しているケースだ。このような場合、マテリアルをロードすると、それに依存するテクスチャも自動的にロードされる。検証では、マテリアルをロードした後に、そのマテリアルが参照するテクスチャだけをAddressables.Releaseで解放しようとしても、マテリアルがまだテクスチャを参照しているため、実際にはテクスチャのメモリが解放されないことが確認された。テクスチャをメモリから解放するには、マテリアルへの参照も全て解除し、最終的にマテリアル自体もAddressables.Releaseする必要がある。この挙動は、依存関係のあるアセットを管理する上で非常に重要であり、メモリリーク(不要なメモリが解放されずに残り続ける問題)を防ぐためには、依存関係の解消を意識した解放処理が必要となる。
Addressablesは、内部的にUnityの「AssetBundle(アセットバンドル)」という技術を利用している。AssetBundleは、複数のアセットを一つのファイルにまとめることで、ネットワーク経由での配信や、効率的なアセット管理を可能にする仕組みだ。Addressablesでは、アセットをAssetBundleにまとめる際の構成方法をいくつか設定できる。例えば、「Pack Together」は複数のアセットを一つのAssetBundleにまとめる設定で、「Pack Separately」は各アセットを個別のAssetBundleにする設定だ。また、アセットの依存関係を考慮してAssetBundleにまとめる設定もある。
これらの設定によって、AssetBundleのファイルサイズや、ロード時の挙動が大きく変わることが検証で示された。AssetBundleを細かく分割すると、必要なアセットだけをピンポイントでロードできるため、メモリ効率が良くなる傾向がある。しかし、AssetBundleの数が多くなるため、ロード処理の回数が増えたり、管理が複雑になったりする可能性もある。逆に、AssetBundleを大きくまとめると、ロード処理の回数は減るが、不要なアセットまで一緒にロードしてしまうことで、メモリ消費量が増える可能性がある。最適なAssetBundleの構成は、プロジェクトの規模やアセットの利用頻度、更新頻度などによって異なるため、開発者は自身のプロジェクトに合わせて慎重に設計する必要がある。
また、AssetBundleをロードする際には、AssetBundleファイル自体をメモリに読み込むフェーズと、そのAssetBundleの中から個々のアセットをロードするフェーズがある。AssetBundleファイル自体を解放するには、Addressables.Releaseだけでは不十分で、AssetBundleオブジェクトをUnloadする追加の処理が必要になる場合がある。これも、メモリ管理を徹底するための重要なポイントだ。
今回の検証を通じて、UnityのAddressablesはアセット管理を強力にサポートする一方で、その内部挙動を理解せずに使用すると、意図しないロード時間の増加やメモリ消費量の増大を招く可能性があることが明らかになった。特に、初回ロード時のカタログ情報の読み込みやダウンロード、アセットのキャッシュ機構、そしてアセットの依存関係を考慮した適切な解放処理の重要性が浮き彫りになった。Addressablesを効果的に活用するためには、どのアセットをローカルに含めるか、どのグループに入れるか、AssetBundleをどのように構成するかといった初期設計が重要であり、不要になったアセットやシーンを確実にメモリから解放するための戦略的なアプローチが不可欠だ。常にメモリの使用状況とロード時間を監視し、検証で得られた知見を基に、自身のプロジェクトに最適なアセット管理方法を確立することが、高性能で安定したアプリケーション開発へと繋がるだろう。