Unity中的MaterialPropertyBlock的作用和 Material 的区别

发布于:2025-03-30 ⋅ 阅读:(26) ⋅ 点赞:(0)

MaterialPropertyBlock 是 Unity 提供的一个用于动态修改材质属性的轻量级工具,核心作用是避免材质实例化(Material Instantiation),从而优化性能。以下是它的关键特性和使用方法:


1. 核心作用

  • 避免材质实例化
    直接修改 Material 对象(如 material.color = ...)会导致 Unity 创建该材质的独立副本(实例化),增加内存占用和 Draw Call。
    MaterialPropertyBlock 允许多个对象共享同一材质,但拥有独立的属性值(如颜色、纹理)。

  • 动态属性控制
    适合在运行时频繁修改材质属性(如颜色渐变、纹理切换),同时保持渲染性能。


2. 基本用法

// 步骤 1: 获取 Renderer 组件
Renderer renderer = GetComponent<Renderer>();

// 步骤 2: 创建或获取 MaterialPropertyBlock
MaterialPropertyBlock mpb = new MaterialPropertyBlock();
renderer.GetPropertyBlock(mpb); // 获取当前属性块(保留未修改的属性)

// 步骤 3: 修改属性
mpb.SetColor("_BaseColor", Color.red); // 修改颜色
mpb.SetTexture("_BaseMap", myTexture); // 修改纹理

// 步骤 4: 应用到 Renderer
renderer.SetPropertyBlock(mpb);

3. 与直接修改 Material 的区别

特性 直接修改 Material MaterialPropertyBlock
材质实例化 会创建材质副本(内存↑) 共享材质,无副本(内存优化)
性能 频繁调用可能导致卡顿 高效,适合动态属性修改
属性持久化 修改永久生效(保存到材质) 临时修改(仅运行时有效)
适用场景 需要持久化属性修改时 动态效果(如闪烁、颜色渐变)

4. 关键优势

  • 减少Draw Call
    多个对象使用相同的材质和MaterialPropertyBlock时,Unity会自动合并渲染批次(Batching)。

  • 内存友好
    避免因频繁材质实例化导致的内存碎片和泄漏。

  • 灵活控制
    可动态修改材质属性,同时不影响其他使用相同材质的对象。


5. 注意事项

  • 属性名称需匹配
    必须使用着色器中定义的属性名称(如URP中的_BaseColor,而非旧版的_Color)。

  • 属性块生命周期
    MaterialPropertyBlock 是临时对象,需在每次修改时重新应用。
    (例如:在 Update() 中动态修改颜色时,需每帧调用 SetPropertyBlock

  • 线程安全
    只能在主线程中操作(Unity的渲染API非线程安全)。


6. 典型应用场景

  • 角色受伤闪烁
    动态修改 _BaseColor 实现颜色变化,不影响其他角色。
  • 动态环境切换
    批量修改一组对象的纹理(如季节变化)。
  • UI 动态样式
    修改按钮的高光颜色或背景纹理。

示例:批量修改颜色(高效版)

public class BatchColorChanger : MonoBehaviour
{
    public Renderer[] renderers;
    public Color targetColor;

    void Start()
    {
        MaterialPropertyBlock mpb = new MaterialPropertyBlock();
        foreach (var renderer in renderers)
        {
            renderer.GetPropertyBlock(mpb); // 获取当前属性
            mpb.SetColor("_BaseColor", targetColor); // 修改颜色
            renderer.SetPropertyBlock(mpb); // 应用修改
        }
    }
}

总结:MaterialPropertyBlock 是优化运行时材质修改的核心工具,尤其在需要批量处理或动态效果时,能显著提升性能。在URP/HDRP项目中,建议优先使用它替代直接修改材质属性。