【Unity6】Mipmap Streamingを使ったメモリ節約

2024/12/14に公開

概要

Mipmap Streaming(ミップマップテクスチャストリーミング)を使用することで、テクスチャのメモリ使用量を節約することができます。
今回の記事では、Mipmap Streamingを触ってみます。

https://docs.unity3d.com/ja/2021.3/Manual/TextureStreaming.html

環境

Unityバージョン : Unity6000.0.31f1
端末 : iPhoneX

実験1. テクスチャ1000枚をメモリにのせる

Mipmap Streamingの効果を見るため、Mipmap Streamingを使用しない場合のメモリを計測してみます。

  1. 球体を1000個シーンに配置する
  2. それぞれの球体に解像度1024x1024のテクスチャをアサインする (1000枚のテクスチャがメモリに乗る)

使用したテクスチャ

Hoge_1からHoge_1000までの解像度1024x1024のテクスチャ1000枚を用意しています。

使用したC#スクリプト
using UnityEngine;

public class Benchmark : MonoBehaviour
{
    private const int N_X = 17; // 横に並べる個数
    private const int N = 1000; // トータルの個数
    
    void Start()
    {
        var spherePrefab = Resources.Load<GameObject>("Prefabs/Sphere");
        for (int i = 0; i < N; i++)
        {
            var sphere = GameObject.Instantiate(spherePrefab);
            int x = i % N_X - (N_X / 2);
            int z = i / N_X;
            sphere.transform.position = new Vector3(x, 0, z);
            
            var renderer = sphere.GetComponent<MeshRenderer>();
            var material = renderer.material;
            var texture = Resources.Load<Texture2D>($"Textures/Hoge_{i+1}"); // テクスチャ読み込み
            material.mainTexture = texture;
        }
    }
}

結果 : 0.58 GB

テクスチャサイズの合計値は 0.58GB となりました。 (iPhoneXにて計測しています)

テクスチャ1枚あたり0.6MBほどのメモリ消費です

実験2. Mipmap Streaming を有効化する

Mipmap Streamingを有効化すると、
メモリ上にロードするMipmapを削減し、テクスチャサイズの合計値がMemory Budgetで指定したサイズに収まるようになります。
Memory Budgetのサイズが小さすぎると、収まらなくなることがあります (記事の後半で触れます)

今回の実験では、Memory Budget はデフォルト値 512 MB としました。

結果 : 508.3MB

テクスチャサイズの合計値は 508.3MBとなりました。
メモリ上のテクスチャサイズが Memory Budget を超えていないことが確認できます。

テクスチャは基本的にMip0でロードしてますが、
遠景オブジェクトのテクスチャは Mip2がロードされています。

実験3. Memory Budgetを下げる

次に、Memory Budget をさらに減らした時のメモリを見てみます。

Memory Budget : 128MB

Memory Budgetを128 MBに設定してみます。

結果 : 88.0 MB

メモリ上のテクスチャサイズは88.0 MBとなりました。

Memory Budget : 16 MB

Memory Budgetを16 MBに設定してみます。
Max Level Reduciton はデフォルト値 2 です

結果 : 38.7 MB

メモリ上のテクスチャサイズは 38.7MBとなりました。 
Memory Budget を超えるサイズになっていますが、これは Max Level Reduciton = 2 であることが理由です。

Max Level Reductionについて

Mipmap Streamingでは、ロードするMipのレベルを上げてメモリを減らしますが、
Max Level Reductionを超えるレベルのMipをメモリから破棄できません。

Max Level Reduction = 2 の場合、 Mip 1まで破棄できる(Mip 2までロードできる)ため、
テクスチャサイズは 1/16 まで減らすことができます。

Max Level Reduction = 3 の場合、 Mip 2まで破棄できる(Mip 3までロードできる)ため、
テクスチャサイズは 1/64 まで減らすことができます。

今回、Max Level Reduciton = 2 と設定しているため、Mip2までロードできます。

すべてのテクスチャがMipmap2がロードされている

実験4 : Max Level Reduction を増やす

Max Level Reductionを増やすと、より高いレベルのMipを破棄できるため、メモリサイズをさらに減らせるようになります。

以下のようにストリーミングを設定した時のメモリを見てみます。

  • Memory Budget : 16 MB
  • Max Level Reduction : 3

結果 : 12.3 MB

メモリを計測してみると 12.3MB となりました

遠景のテクスチャは Mip3がロードされていることが確認できます。 (近景のテクスチャはMip0,1,2が使用されます)

まとめ

今回はMipmap Streamingのふるまいを確認できました。

  • Memory Budgetに収まるレベルまで、Mipを削減してくれる
  • Max Level Reductionを増やすと、より高いレベルのMipを削減できる (メモリサイズをより減らせるようになる)

その他 : QualitySettings.globalTextureMipmapLimit

QualitySettings.globalTextureMipmapLimitは、Max Level Reductionより優先されます。
https://docs.unity3d.com/6000.0/Documentation/ScriptReference/QualitySettings-globalTextureMipmapLimit.html

QualitySettings.globalTextureMipmapLimitで設定したMipより低いレベルのMipは読み込まれなくなります。

例えば、QualitySettings.globalTextureMipmapLimit = 4 で Max Level Reduction = 2の場合はMip4がロードされます

Discussion