ToggleDrawer
把一個類型的屬性顯示為一個開關,它的值要么是0要么是1。
當選中它時,Unity還會設置一個名為大寫屬性名_ON(可以自定義名字)的shader feature
#pragma shader_feature _SELECTED_ON
我們可以在shader里用過#if、#ifdef或者#if defined關鍵詞來判斷它當前是否被開啟。
shader文件:
Properties
{
...
[Toggle]_selected("selected", Int) = 0
...
}
...
SubShader
{
...
#pragma shader_feature _SELECTED_ON
...
#ifdef _SELECTED_ON
...
#else
...
#endif
...
}
設置屬性
1. 設置接口 EnableKeyword/DisableKeyword
At runtime, the appropriate shader variant is picked up from the Material keywords (Material.EnableKeyword and DisableKeyword) or global shader keywords (Shader.EnableKeyword and DisableKeyword).
2. keyword的兩種方式
Toggle displays a float as a toggle. The property value will be 0 or 1, depending on the toggle state.
When it is on, a shader keyword with the uppercase property name +"_ON" will be set, or an explicitly specified shader keyword.
- uppercase property name +"_ON"
// Will set "_INVERT_ON" shader keyword when set
[Toggle] _Invert ("Invert?", Float) = 0
- an explicitly specified shader keyword
// Will set "ENABLE_FANCY" shader keyword when set.
[Toggle(ENABLE_FANCY)] _Fancy ("Fancy?", Float) = 0
我們使用的而是第一種方式.
設置代碼如下:
self._fogMaterial = self.fogObj:GetComponent("Renderer").material
選中
self._fogMaterial:EnableKeyword("_SELECTED_ON")禁用
self._fogMaterial:DisableKeyword("_SELECTED_ON")
遇到的問題
問題: 打包后,真機運行時EnableKeyword失效了。
原因: Unity在Build時自動把沒有被任何用到的材質使用的variant裁切了(Shader build time stripping)
While building the game, Unity can detect that some of the internal shader variants are not used by the game, and skip them from build data. Build-time stripping is done for:
生成游戲包時,Unity可以檢測到某些內在著色器變體沒有被使用,然后stripping(裁切、忽略)它們。生成時去除可用于:
Individual shader features, for shaders that use
#pragma shader_feature
. If none of the used materials use a particular variant, then it is not included into the build. See internal shader variants documentation. Out of built-in shaders, the Standard shader uses this.個別著色器特性,使用
#pragma shader_feature
的著色器。如果一個變體沒有被任何用到的材質使用,那么生成時就不把它打進去。參考內在著色器文檔 ,內置著色器中的標準著色器使用這種方式。
方案很多:
- Shader加入到Edit->Project Settings->Graphics->Always Included Shaders這個列表里
加入AlwaysIncludedShaders的shader是開始游戲的時候就全部編譯了嗎?
答案是不會,加到always include 的shader,會將shader的所有變體打包到游戲,用到的時候才會加載用到的變體到內存!
相關文檔:https://docs.unity3d.com/Manual/OptimizingShaderLoadTime.html
Under all default settings, Unity loads the object into memory, but does not create the until they are actually needed.
This means that shader variants that are included into the game build can still potentially be used, but there’s no memory or load time cost paid until they are needed. For example, shaders always include a variant to handle point lights with shadows, but if you never end up using a point light with shadows in your game, then there’s no point in loading this particular variant.
新建一個材質,將被裁切的variant選中,這樣被材質使用到的variant不會stripping ( If none of the used materials use a particular variant, then it is not included into the build)
修改Shader -- multi_compile
#pragma shader_feature
改為#pragma multi_compile
舊版:#pragma shader_feature _SELECTED_ON
新版:#pragma multi_compile __ _SELECTED_ON
Individual shader features, for shaders that use
#pragma shader_feature
. shader_feature才會Shader build time stripping
我采用方案3.
參考鏈接
Making multiple shader program variants : https://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html
MaterialPropertyDrawer : https://docs.unity3d.com/ScriptReference/MaterialPropertyDrawer.html