AssetBundleから参照されるcgincファイルにはAssetBundle名をつけないとcgincの更新が反映されない現象と対応方法です。
Unity2018.2
2019/2/20追記
Unity2018.3.1で直っているかも?というコメントをいただいたので試してみました。
手元にあったUnity2018.3.6で試してみたところ・・・確かに修正されていました!
- MaterialにだけAssetBundle名を付けてcgincやShaderにはAssetBundle名を付けなかった場合
- ShaderにだけAssetBundle名を付けてcgincやMaterialにはAssetBundle名を付けなかった場合
の両方とも正常にAssetBundleがビルドされることを確認しました。
情報ありがとうございます!
準備
まず検証用のcgincファイルを作ります。
色を適当に返すGetColor()
という関数だけが定義されています。
#ifndef EXAMPLE_INCLUDED #define EXAMPLE_INCLUDED inline float4 GetColor(){ return float4(1, 0, 0, 1); } #endif
つぎにこれをシェーダから読み込みます。
上記のcgincのGetColor()
の結果を返すだけのシェーダです。
Shader "Unlit/shader_assetbundle_example" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "cginc_assetbundle_example.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag (v2f i) : SV_Target { return GetColor(); } ENDCG } } }
さらにこれをMaterialにセットします。
ここまでで3つのファイルができました。
問題点
前節のファイルのうちMaterialだけをAssetBundleにします。
すると当然、MaterialのほかにShaderやテクスチャが含まれたAssetBundleが出来上がります。
ここで一度このAssetBundleをビルドして、AssetBundleからMaterialを読み込みます。
ロードはこんな感じで適当に。
using UnityEngine; public class AssetBundleExample : MonoBehaviour { [SerializeField] private string _assetBundlePath; [SerializeField] private string _assetPath; private void Start() { var assetBundle = AssetBundle.LoadFromFile(_assetBundlePath); var material = assetBundle.LoadAsset<Material>(_assetPath); GetComponent<MeshRenderer>().material = material; assetBundle.Unload(false); } }
結果は正常にcgincで定義した色が反映されます。
問題はここからです。
この状態でcgincのGetColor()
で定義した色だけ変えてみます。
// 黄色に変更 inline float4 GetColor(){ return float4(1, 1, 0, 1); }
次にAssetBundleを差分ビルド(既存のAssetBundleを消さずにビルド)します。
そしてまた上記と同様にMaterialを読み込みます。
すると、色を黄色に変えたにもかかわらず赤のまま変わらないという結果が得られます。
これはShaderファイルだけをAssetBundle化して読み込んだ場合も同様です。
解決方法
解決方法としてはShaderとcgincにちゃんとAssetBundle名を付けるというのが正しそうです。
今回のケースではMaterialとShaderとcgincにすべて同じAssetBundle名を付けても解決しますが、
実用性を考えるとShaderとcgincを一つのAssetBundleとするのがよさそうです。
この方法であればcgincだけを更新して差分ビルドをしても正常に更新されます。
ちなみにですが、差分ビルドをやめてすべてのAssetBundleをビルドしなおせば
上記の対応をしなくても正常にcgincの変更が反映されるようです。
が、実用的じゃないので割愛しています。