見出し画像

[Unity]ShaderVariantについて~中編:AssetBundleとShaderVariantの関係~

ShaderVariantシリーズの中編です。

前編では、ShaderVariantとは何なのか?を述べてきました。
今回は、AssetBundleとShaderVariantの関係をお話していきたいと思います。

■AssetBundleとShader Variantによる問題

突然ですが、「AssetBundleで動作するようにしたら、見た目が変わってしまったー」そんなことないでしょうか?
これAssetBundleとShaderVariantの関係にハマってしまっているケースがあります。

画像1

上記のようにAssetBundle化してロードすると、変になってしまうケースありませんか?

■原因を探るためにはFrameDebuggerでの確認が有効です

画像2

まずは、Sceneに配置した時です。
ここで最も注目するのはKeywordsの項目です。
「DIRECTIONAL SHDOW_SCREEN LIGHTPROBE_SH _NORMALMAP」
となっていますね。

画像3

そして、AssetBundleから読み込んだ時です。
Keywordsは「DIRECTIONAL SHDOW_SCREEN LIGHTPROBE_SH 」
となっていて、「_NORMALMAP」がなくなってしまっています。

これはAssetBundleをビルドした時に、ShaderVariantのストリッピングが行われてしまったために、このような現象に見舞われます。

■ShaderVariantのストリッピング?

前編でも軽く述べましたが…。
Unityではビルドするときに、利用していないVariant( keywordの組み合わせ) を何となく汲み取って、ビルドの過程で省きます。
これをShaderVariantのストリッピングと言うのですが、これによってAssetBundleをビルドした際に「『_NORMALMAP』は使わないっぽいし、省きましょう」と判断されてしまっています。

■なぜShaderがストリッピングされたのか…

画像4

このような形でShaderだけをまとめたAssetBundleを作成していないでしょうか?(※オレンジの枠線は暗黙的にAssetBundleに含まれるファイルです)
その場合、Unityでは shader.bundle内に登録されているアセットの情報をもとにShaderVariantのストリッピングを行います。
ここでは MyShader.shaderのみで判断を行います。
もしMaterialも含まれていたら、正しく判断が行われて表示がずれる結果にはなりません。

ベストな方法は?

画像5

ベストな方法は「ShaderVariantCollectionを作成して、Shaderと同じAssetBundleに格納する」です。

■ShaderVariantCollectionとは?

画像6

ShaderVariantCollectionとは、上の画像のようにShaderとkeywordを登録するためのアセットファイルです。

このShaderではこういうKeywordを使いますよと宣言しておく事で、本来必要だった部分がストリッピングを回避することが出来ます。

こちらを用意しておくことでWarmupしておくなど最適化の面でも有利になります。その辺の詳しい話は 後編 で行います。

ShaderVariantCollection作るのめんどくさくない?

そう思って、上記のパッケージを作りました。

Keywordを正しく把握するためにはFrameDebuggerで常に確認していって、それをShaderVariantCollectionに反映させていくことが重要です。

ただFrameDebuggerで逐一Keywordを目視して確認していくのは、あまりに現実的な作業ではありません。

「FrameDebuggerのkeyword集計作業を自動化して、そこからShaderVariantCollectionアセットファイルを作るのも自動化する」そういう所を目指してこのツールを作成しました。

あとついでにAssetBundleにあるShaderがどのkeyword含んでるか知りたい

そう思って、AssetBundleを読み込んで、ShaderVariantを解析するEditor拡張を作ってみました!書き出しはJsonファイルを書き出します。

最後の後編では、ShaderVariantと最適化周りについてお話して行きます。

この記事が気に入ったらサポートをしてみませんか?