Unity3D Mesh中material和sharedMaterial的区别及内部实现的推断是怎样的

发布时间:2021-11-15 16:44:34 作者:柒染
来源:亿速云 阅读:685

Unity3D Mesh中material和sharedMaterial的区别及内部实现的推断

引言

在Unity3D中,MeshRenderer组件用于渲染3D模型,而Material则是定义模型外观的关键组件。在MeshRenderer中,有两个与材质相关的属性:materialsharedMaterial。这两个属性在表面上看起来非常相似,但它们在内部实现和使用场景上有着显著的区别。本文将深入探讨materialsharedMaterial的区别,并尝试推断它们的内部实现机制。

1. materialsharedMaterial的基本概念

1.1 material属性

materialMeshRenderer组件的一个属性,用于获取或设置当前渲染器所使用的材质。当你通过material属性获取材质时,Unity会返回一个实例化的材质副本。这意味着你对这个材质的任何修改都不会影响到其他使用相同材质的渲染器。

MeshRenderer renderer = GetComponent<MeshRenderer>();
Material mat = renderer.material;
mat.color = Color.red; // 只影响当前渲染器

1.2 sharedMaterial属性

sharedMaterial同样是MeshRenderer组件的一个属性,但它返回的是渲染器所使用的共享材质。与material不同,sharedMaterial返回的是材质的引用,而不是副本。因此,对sharedMaterial的任何修改都会影响到所有使用该材质的渲染器。

MeshRenderer renderer = GetComponent<MeshRenderer>();
Material sharedMat = renderer.sharedMaterial;
sharedMat.color = Color.blue; // 影响所有使用该材质的渲染器

2. materialsharedMaterial的区别

2.1 实例化与引用

material属性返回的是材质的实例化副本,而sharedMaterial返回的是材质的引用。这意味着:

2.2 性能影响

由于material属性会创建新的材质实例,因此频繁使用material属性可能会导致性能问题。每次调用material属性时,Unity都需要分配内存来存储新的材质实例,这可能会导致内存碎片化和性能下降。

相比之下,sharedMaterial属性不会创建新的材质实例,因此它的性能开销较小。然而,由于sharedMaterial是共享的,对它的修改会影响到所有使用该材质的渲染器,这可能会导致意外的副作用。

2.3 使用场景

3. 内部实现的推断

3.1 material属性的内部实现

当调用material属性时,Unity可能会执行以下步骤:

  1. 检查是否已有实例化材质:Unity首先检查当前渲染器是否已经有一个实例化的材质。如果有,则直接返回该材质。
  2. 创建新的材质实例:如果没有实例化材质,Unity会创建一个新的材质实例,并将其赋值给渲染器。这个新实例是基于sharedMaterial的副本。
  3. 返回新实例:最后,Unity返回这个新创建的材质实例。
public Material material
{
    get
    {
        if (m_InstanceMaterial == null)
        {
            m_InstanceMaterial = new Material(sharedMaterial);
        }
        return m_InstanceMaterial;
    }
    set
    {
        m_InstanceMaterial = value;
    }
}

3.2 sharedMaterial属性的内部实现

sharedMaterial属性的实现相对简单,因为它只是返回材质的引用。Unity可能会执行以下步骤:

  1. 返回共享材质:Unity直接返回渲染器所使用的共享材质引用。
public Material sharedMaterial
{
    get
    {
        return m_SharedMaterial;
    }
    set
    {
        m_SharedMaterial = value;
    }
}

3.3 内存管理

由于material属性会创建新的材质实例,Unity需要管理这些实例的生命周期。当渲染器被销毁或材质被替换时,Unity需要确保这些实例化的材质被正确释放,以避免内存泄漏。

void OnDestroy()
{
    if (m_InstanceMaterial != null)
    {
        Destroy(m_InstanceMaterial);
    }
}

4. 实际应用中的注意事项

4.1 避免频繁调用material属性

由于material属性会创建新的材质实例,频繁调用它可能会导致性能问题。因此,在需要为每个渲染器单独定制材质的场景中,建议在初始化时一次性获取material属性,并将其存储在变量中以便后续使用。

MeshRenderer renderer = GetComponent<MeshRenderer>();
Material mat = renderer.material;

// 后续直接使用mat变量
mat.color = Color.red;

4.2 谨慎使用sharedMaterial属性

由于sharedMaterial属性返回的是共享材质引用,对它的修改会影响到所有使用该材质的渲染器。因此,在需要统一管理材质的场景中,建议在修改sharedMaterial之前备份原始材质,以便在需要时恢复。

MeshRenderer renderer = GetComponent<MeshRenderer>();
Material originalMat = renderer.sharedMaterial;

// 修改sharedMaterial
renderer.sharedMaterial.color = Color.blue;

// 恢复原始材质
renderer.sharedMaterial = originalMat;

4.3 使用MaterialPropertyBlock优化性能

在某些场景中,可能需要对多个渲染器使用相同的材质,但需要为每个渲染器设置不同的属性(如颜色、纹理偏移等)。在这种情况下,可以使用MaterialPropertyBlock来避免创建多个材质实例。

MeshRenderer renderer = GetComponent<MeshRenderer>();
MaterialPropertyBlock propBlock = new MaterialPropertyBlock();
renderer.GetPropertyBlock(propBlock);

// 设置属性
propBlock.SetColor("_Color", Color.green);
renderer.SetPropertyBlock(propBlock);

5. 总结

materialsharedMaterial是Unity3D中MeshRenderer组件的两个重要属性,它们在内部实现和使用场景上有着显著的区别。material属性返回的是材质的实例化副本,适用于需要为每个渲染器单独定制材质的场景;而sharedMaterial属性返回的是材质的引用,适用于需要统一管理材质的场景。

在实际应用中,开发者应根据具体需求选择合适的属性,并注意避免频繁调用material属性以优化性能。此外,使用MaterialPropertyBlock可以进一步优化性能,特别是在需要为多个渲染器设置不同属性的场景中。

通过深入理解materialsharedMaterial的区别及内部实现机制,开发者可以更好地管理Unity3D中的材质,提升应用的性能和可维护性。

推荐阅读:
  1. GitHub上发现的一个导出Unity3D场景数据的工具
  2. Unity3D静态对象优化系列三

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

material

上一篇:Centos7如何安装Redmine3.4.5

下一篇:centos 7以上版本安装vmtools时提示kernel路径问题怎么办

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》