その他
    ホーム 技術発信 DoRuby 【Unity】テクスチャの”Generate Mip Maps”を自動でオフにして手間とメモリを省きたい
    【Unity】テクスチャの”Generate Mip Maps”を自動でオフにして手間とメモリを省きたい
     

    【Unity】テクスチャの”Generate Mip Maps”を自動でオフにして手間とメモリを省きたい

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    テクスチャのインポート設定での一つである “Generate Mip Maps” を自動でオフにする方法を考えます。

    はじめに

    こんにちは、inoooooocchiです。
    気付けばあと2週間程度で10月。
    入社から半年が経過しようとしていることにびっくりしています。早すぎます。

    そんなこんなで今までやってきた作業や実装内容を思い返していたのですが、毎週のように行っている作業の中でおまじない的に行っているものがあり、「この一手間によって何がどう変わるんだろう…」と思ったため、調べてみました。

    その作業とは、テクスチャのインポート です。
    私はオンラインゲーム部に所属しているエンジニアなので、ゲームのUIなどで新しいグラフィックを使う際には、Unityにテクスチャをインポートする必要があります。
    この業務内容を教わる際、先輩から「インポートしたらGenerateMipMapsのチェックをオフにすること」と教わっていました。
    もちろんその時に説明をして頂いたのですが、当時は入社直後で覚えることが多く、大まかな流れを覚えるだけで精一杯でした。

    と、いうことで、GenerateMipMapsのチェックをオフにする 意味を追い求めて行きます。

    MipMapとは?

    GenerateMipMaps…つまり、MipMapを生成するということなのですが、
    そもそもMipMapってなに?
    という疑問が浮かんできました。

    Unityの公式マニュアルによると、

    ミップマップはかなり小さくした画像イメージを複数集めた一覧であり、これによりリアルタイム 3D エンジンでのパフォーマンスを最適化します。カメラから遠く離れたオブジェクトはテクスチャの小さいものを使用します。ミップマップを使用すると 33% 多くメモリを使用しますが、使用しないとパフォーマンスのロスが顕著になります。

    とのこと。
    どうやら、縮小したテクスチャのリストのようなもので、カメラとの距離が離れて小さく描画する必要がある際に、ミップマップの中から適切なサイズのテクスチャを選んで描画する、といったもののようです。
    リストを保持しておくためにメモリ使用量は増えますが、描画の際に小さなサイズを描画させることが出来るのでパフォーマンスが良くなるということでしょうか。

    MipMapの効果検証

    MipMapの意味が分かったところで、何故GenerateMipMapsのチェックをオフにするのか考えてみます。

    先ほどのマニュアルの説明では、”リアルタイム 3D エンジンでのパフォーマンスを最適化”するためにMipMapを使っていると書かれていました。
    つまり2Dでゲームを制作する場合、カメラとの距離も何も無いので、基本的に使われることは無さそうです。
    ただし、2Dでもテクスチャを縮小して使いたい場合はあります。
    そのような時にMipMapがどのような影響を及ぼすのか、実際に見てみました。

    今回は、MipMapによる描画の違いの例として、
    弊社Appiritsのゲームシリーズ「式姫プロジェクト(公式サイト:式姫大全)」から「狛犬(詳細はこちら)」に出演して頂きました。

    • GenerateMipMaps オン
      enter image description here
    • GenerateMipMaps オフ
      enter image description here

    この例では、もともとのサイズが1024×1024のテクスチャを300×300のImageにアタッチしています。
    一目瞭然ですが、MipMapを使っている方は全体的にアンチエイリアスがかかり、少し滲んだ感じがしますが、滑らかに表示されています。
    一方、MipMapを使わない方は、ジャギーが目立ちますが色合いや細部ははっきりと表示されています。

    このように、どうやら2DでもMipMapによって画像の描画の仕方が変わるようです。

    ゲームのUIにおけるMipMap

    さて、先ほどはテクスチャのサイズを元より小さくした際にMipMapが適用されることを確認しましたが、ゲームのUIに使うテクスチャのように、サイズが変動しないことを前提としているテクスチャもあると思います。
    これらのテクスチャに対し、GenerateMipMapsをオンにしてしまうと、使いもしないのに縮小されたテクスチャが生成されることになってしまいます。

    これでようやく、私のインポート作業の中でGenerateMipMapsのチェックをオフにする意味がはっきりしました。
    UIに使うテクスチャはMipMapを生成しても使わないので生成するだけメモリの無駄!
    ということですね。

    インポート作業を簡単にしよう

    というわけで、テクスチャをインポートするたびにGenerateMipMapsをオフにする作業をこれからも続けていかなければならないわけですが、「2DゲームだからMipMapいらないか…」と割り切ってしまえば、この作業は簡単に自動化出来ます。

    以下のスクリプトファイルを作成することで、インポート時及びインポート設定の変更時に、GenerateMipMapsを自動でオフにしてくれます。

    using UnityEditor;
    using UnityEngine;
    
    public class TextureImportProcessor : AssetPostprocessor {
        // インポート設定のデフォルト値をインポート前に変更可能
        public void OnPreprocessTexture(){
            // assetImporterがインポート設定を持っている
            var importer = assetImporter as TextureImporter;
    
            // GenerateMipMapsをオフにする
            importer.mipmapEnabled = false;
        }
    }
    

    AssetPostprocessorというクラスを継承することで、インポート処理にフックしてスクリプトを実行することが出来ます。
    今回はテクスチャのインポート設定を変更したいので、TextureImportProcessorというクラスを作りました。

    OnPreprocessTexture関数は、インポート処理の前に呼び出されます。この時点でインポート設定を変更しておけば、インポートされるテクスチャの設定にその変更が自動的に反映されます。

    AssetPostprocessorの詳細に関しては、公式のスクリプトリファレンスを見ればなんとなく分かると思います。

    余談ですが、上記のスクリプトを使う場合、どう頑張ってもGenerateMipMapsをオンに出来ません。
    オンにして設定を保存すると、即座にオフに変更されるからです。
    UIだけオフにしたい等の場合は、UIとそれ以外でテクスチャのディレクトリや命名規則を分け、スクリプト内で判定して区別してあげる必要があります。

    最後に

    簡単なスクリプトを書くだけで、作業の手間が省けるのは非常にありがたいですね。
    Unityの拡張性の高さに、改めて驚かされますね。
    DoRubyでは、他のライターの方がUnityのエディタ拡張について書いているため、興味があればそちらもご覧ください。
    UnityEditor上で複数のゲームオブジェクトをプレハブ化する方法)

    これまた余談ですが、弊社のゲーム作品「かくりよの門」及び「うつしよの帳」で使われている式姫スタンプの、狛犬の「突撃ッスー!」がアホ丸出しでなんだか好きです。