[Unity]ShaderVariantについて~中編:AssetBundleとShaderVariantの関係~
ShaderVariantシリーズの中編です。
前編では、ShaderVariantとは何なのか?を述べてきました。
今回は、AssetBundleとShaderVariantの関係をお話していきたいと思います。
■AssetBundleとShader Variantによる問題
突然ですが、「AssetBundleで動作するようにしたら、見た目が変わってしまったー」そんなことないでしょうか?
これAssetBundleとShaderVariantの関係にハマってしまっているケースがあります。
上記のようにAssetBundle化してロードすると、変になってしまうケースありませんか?
■原因を探るためにはFrameDebuggerでの確認が有効です
まずは、Sceneに配置した時です。
ここで最も注目するのはKeywordsの項目です。
「DIRECTIONAL SHDOW_SCREEN LIGHTPROBE_SH _NORMALMAP」
となっていますね。
そして、AssetBundleから読み込んだ時です。
Keywordsは「DIRECTIONAL SHDOW_SCREEN LIGHTPROBE_SH 」
となっていて、「_NORMALMAP」がなくなってしまっています。
これはAssetBundleをビルドした時に、ShaderVariantのストリッピングが行われてしまったために、このような現象に見舞われます。
■ShaderVariantのストリッピング?
前編でも軽く述べましたが…。
Unityではビルドするときに、利用していないVariant( keywordの組み合わせ) を何となく汲み取って、ビルドの過程で省きます。
これをShaderVariantのストリッピングと言うのですが、これによってAssetBundleをビルドした際に「『_NORMALMAP』は使わないっぽいし、省きましょう」と判断されてしまっています。
■なぜShaderがストリッピングされたのか…
このような形でShaderだけをまとめたAssetBundleを作成していないでしょうか?(※オレンジの枠線は暗黙的にAssetBundleに含まれるファイルです)
その場合、Unityでは shader.bundle内に登録されているアセットの情報をもとにShaderVariantのストリッピングを行います。
ここでは MyShader.shaderのみで判断を行います。
もしMaterialも含まれていたら、正しく判断が行われて表示がずれる結果にはなりません。
■ベストな方法は?
ベストな方法は「ShaderVariantCollectionを作成して、Shaderと同じAssetBundleに格納する」です。
■ShaderVariantCollectionとは?
ShaderVariantCollectionとは、上の画像のようにShaderとkeywordを登録するためのアセットファイルです。
このShaderではこういうKeywordを使いますよと宣言しておく事で、本来必要だった部分がストリッピングを回避することが出来ます。
こちらを用意しておくことでWarmupしておくなど最適化の面でも有利になります。その辺の詳しい話は 後編 で行います。
■ShaderVariantCollection作るのめんどくさくない?
そう思って、上記のパッケージを作りました。
Keywordを正しく把握するためにはFrameDebuggerで常に確認していって、それをShaderVariantCollectionに反映させていくことが重要です。
ただFrameDebuggerで逐一Keywordを目視して確認していくのは、あまりに現実的な作業ではありません。
「FrameDebuggerのkeyword集計作業を自動化して、そこからShaderVariantCollectionアセットファイルを作るのも自動化する」そういう所を目指してこのツールを作成しました。
■あとついでにAssetBundleにあるShaderがどのkeyword含んでるか知りたい
そう思って、AssetBundleを読み込んで、ShaderVariantを解析するEditor拡張を作ってみました!書き出しはJsonファイルを書き出します。
最後の後編では、ShaderVariantと最適化周りについてお話して行きます。
この記事が気に入ったらサポートをしてみませんか?