????????本篇總結了Unity中renderer的3種常用的材質相關的變量:renderer.material,renderer.sharedMaterial,renderer.MaterialPropertyBlock。以及三者對SRPBatcher的影響。
一.介紹及對比
1.概念介紹
1.material
定義:material 是Render組件(如MeshRenderer)的實例化材質。
特點:
訪問renderer.material會自動復制一份材質實例(如果之前是共享的),這樣你修改這個材質只影響當前物體,不會影響其他使用同一材質的物體。適合給單個物體做特定修改,比如改顏色、貼圖等。
性能:實例化材質會額外占用內存,修改頻繁會增加GC壓力。
2. sharedMaterial
定義:sharedMaterial 是Render使用的共享材質資源,多個物體可以共用同一份材質實例。
特點:
修改sharedMaterial會影響所有使用該材質的物體。適合修改全局材質,比如編輯場景中統一的材質。
性能:不會產生額外實例,節省內存。
3.materialPropertyBlock
定義:materialPropertyBlock(簡稱MPB)是用于臨時覆蓋材質屬性的一個工具,可以在不實例化材質的情況下,給單個 Renderer 設置不同的材質屬性(如顏色、紋理、浮點參數等)。
特點:
不會創建新的材質實例,也不會修改共享材質本身。
只影響當前 Renderer 的渲染效果,方便批處理且性能友好。
適用于需要大量物體同用一個材質,但表現出不同屬性(顏色、亮度等)時使用。
var mpb = new MaterialPropertyBlock();
renderer.GetPropertyBlock(mpb);
mpb.SetColor("_Color", Color.green);
renderer.SetPropertyBlock(mpb);
2.對比
特性 | material | sharedMaterial | MaterialPropertyBlock |
---|---|---|---|
是否實例化材質 | 是,自動實例化 | 否,共享材質 | 不實例化材質,僅覆蓋屬性 |
是否影響所有物體 | 否,只影響當前 Renderer | 是,影響所有使用該材質物體 | 否,只影響當前 Renderer |
適用場景 | 單獨修改某個物體的材質屬性 | 修改所有使用該材質的物體時(全局修改) | 大批量物體不同屬性但共用材質的場景 單個物體臨時修改材質參數,且避免實例化材質 |
性能影響 | 較大,可能導致內存和GC開銷 | 較小 | 較小,性能友好 |
數據存儲位置 | 獨立材質實例 | 資源文件 | 臨時GPU參數覆蓋 |
注意 | 避免頻繁使用,適合少量特殊對象 | 慎用,通常用于編輯器或者全局風格調整 | 盡量讓共享一組參數的物體使用相同 MPB 數據,避免每個物體都用不同數據 |
二.分別對SRPBatcher的影響
1.render.material
訪問render.material 會實例化材質(clone),導致該物體的材質不再是共享的。
實例化材質意味著該物體擁有自己獨立的材質狀態,哪怕其他物體材質完全一樣,也不再視為“同一材質”。
renderer.material.color = Color.red;
訪問 render.material會自動給該 Renderer 創建一份新的材質實例(也就是材質的“實例化”),然后返回這份實例。
因此,SRPBatcher 無法將該物體與使用共享材質的物體合批,會破壞批處理。
底層原因:SRPBatcher 判斷材質是否相同通常基于材質實例(Material instance)是否完全匹配。實例化后材質地址不同,狀態不一致,批處理被打斷。
2. render.sharedMaterial
多個物體共享同一個sharedMaterial,材質狀態完全一致。
這符合 SRPBatcher 的批處理條件,有利于批處理的實現。(也是一種享元思想在資源內存方面的體現)
因此,使用sharedMaterial是保證 SRPBatcher 批處理有效的前提之一。
3.MaterialPropertyBlock?
MaterialPropertyBlock可以在不實例化材質的前提下,臨時覆蓋單個 Renderer 的材質參數。
Unity 的 SRPBatcher 對部分類型的屬性(例如可批處理的常量緩沖區參數)支持合批處理,即使有不同的MaterialPropertyBlock。
但如果 MPB 修改了不能合批的參數(比如部分紋理資源),也可能導致批處理失敗。
總體來說,合理使用 MPB 能最大化利用 SRPBatcher 性能優勢,同時實現物體個性化表現。
不合理用法:多個物體使用不同的MPB
foreach (var cube in cubes){var renderer = cube.GetComponent<Renderer>();var mpb = new MaterialPropertyBlock();// 每個物體顏色不同,都會生成不同的MPB數據mpb.SetColor("_Color", Random.ColorHSV()); renderer.SetPropertyBlock(mpb);}
合理用法:統一MPB數據
var mpb = new MaterialPropertyBlock();mpb.SetColor("_Color", color); // 所有物體共享同一個顏色參數foreach (var cube in cubes){var renderer = cube.GetComponent<Renderer>();// 共享同一個 MPB 數據,SRPBatcher 可合批renderer.SetPropertyBlock(mpb);}
本篇完