Unity知识点-Renderer常用材质变量
本篇总结了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);}
本篇完