ShaderはAssetBundleに含まれるのか?本当のところどうなの?
例えばModelとMaterioalをAssetBundle化して配信したとします。
その時AssetBundleに含まれるのはShaderへの参照のみなのか、それとも?
実際に検証してみた
※検証環境はUnity5.5系です
※アプリは検証対象のShaderをストリッピングしないようにしています。
検証1
- 既存のアプリにはない新規Shaderを適用したAssetBundleを配信してみる
- この状態では正しくレンダリングされない
- 新規Shaderを含んだアプリで同じAssetBundleを読み込んでみる
- 想定した通りのレンダリング結果となる
AssetBundleに含まれるのは参照のようなもので、あくまでアプリ側にShaderが含まれている必要があるように思える。
検証2
- 既存のShaderの処理本体(CGPROGRAM〜ENDCG)を書き換えたアプリで、以前作ったAssetBundleを読み込んでみる
- 書き換えた通りにレンダリング結果がかわる
- また、この時新しいPropertyを追加していたとしても、そのPropertyにアクセスできる(そのままだとデフォルト値だけど)。
このパターンも検証1での結果と同じ結論になりそう。
検証3
- 既存のShaderに対して、ZWriteやZTestなどの設定を書き換えて作ったアプリで、既存のAssetBundleを読み込んでみる。
- 書き換える前のShaderと同じ動作をする!
なぜ!?
Propertyの値やレンダリング順序に関しては、AssetBundleを作った時のMaterialのプロパティに含まれているため、
そこが参照されるのはわかる。
でも、ZWriteやZTestの変更が適用されないのはなんでだ?
もしやShaderのセッティング(Tagsとか)に関してはAssetBundleに含まれている!?
気のせい!?気のせいなの?
何かミスった?
これだとあとでShaderの実装をまとめて変更しようとした場合、内容によってはすでに配信しているAssetBundleが大量にあったら困っちゃう。
検証3のケースへの(とりあえず)対応
アプリの実行時に「Shader.Find(material.shader.name)」的なコードでShaderを再設定してあげると、正しく変更が適用されました。
結論
色々ググったりしてみたものの、結局のところAssetBundleにどこまでの情報が含まれているのかは謎。
試した範囲では参照を含んでいるっぽい挙動をしているけど、場合によって変な対応を強いられる。
うーん。。。何かAssetBundleを作るとき(あるいはプロジェクト)の設定によるとかあるのかなー。