第十一课 Unity编辑器创建的资源优化_预制体和材质篇(Prefabs和Materials

[复制链接]
发表于 2024-12-5 10:50:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
预制体(Prefabs)

Unity中的预制体是用来存储游戏对象、子对象及其所需组件的可重用资源,一样平常来说预制体资源可充当资源模版,在此模版基础上可以在场景中创建新的预制体实例。
利用预制体的好处
   

  • 由于预制体体系可以主动保持所有实例副本同步,因此可以比单纯地简单复制粘贴游戏对象做到更好的对象管理。
  • 此外通过预制体嵌套(Nested Prefabs)可以将一个预制体嵌套到另一个预制体中,从而创建多个易于编辑的复杂游戏对象层级视图。
  • 可以通过覆盖各个预制体实例的设置来创建预制体变体(Prefabs Variant),从而可以将一系列覆盖组合在一起形成故意义预制体的厘革。
  嵌套预制体与单预制体相比的长处与缺点
   长处:
  

  • 嵌套预制体方便预制体管理,方便资源重复利用,易于统计场景复杂度
  • 美术制作时可以比力合理的分配UV,和贴图利用率
  • 方便关卡设计职员发挥,充分合理利用资源
  • 嵌套预制体比力方便利用工具做LOD,LOD结果也比力好
  • 嵌套预制体修改方便,只需修改子预制体就可以做到所有嵌套预制体同步
  • 比力方便做场景遮挡剔除,可以做到精致的遮挡剔除优化结果
  缺点:
  

  • 手动做Bundle依赖时要按Scene方式处理,依赖关系较为复杂
  • 大概会增长材质数量与Drawcall数量
  • 不太适合做大规模远景对象。
  • 美术与关卡设计职员要充分思量组合复杂度与特例场景表现,避免重复性和单一性,需要更多的沟通成本
     
  利用Prefab变体的一些限制
   - 不能改变本体Prefab游戏对象 (GameObject)层级
- 不能删除本体Prefab中的游戏对象,但可以通过Deactive游戏对象来到达与删除游戏对象同样的结果
- 对于Prefab变体要保持其Override属性的厘革,不能通过Apply to base把这些厘革应用到本体Prefab上,这样会破坏基础Prefab的结构和功能。
  
材质(Materials)

材质球是决定物体怎样渲染的重要功能。虽然这是一个熟悉的特性,但如果利用不当,它很容易导致内存走漏。
简单地访问一个参数将复制它
关于Material,最重要的是要记住,它们可以简单地通过访问它们的参数来复制。而且很难留意到它正在被复制。 
  1. Material material;
  2. void Awake()
  3. {
  4.     material = renderer.material;
  5.     material.color = Color.green;
  6. }
复制代码
这是一个简单的过程,将材质的颜色属性设置为color .green。
渲染器的材质是重复的。复制的对象必须是显式的,
利用实例删除重复的Material
  1. Material material;
  2. void Awake()
  3. {
  4.     material = renderer.material;
  5.     material.color = Color.green;
  6. }void OnDestroy(){    if (material != null)    {        Destroy(material)    }}
复制代码
以这种方式烧毁重复的材料可以避免内存走漏。
彻底清理天生的材质球
动态天生的材料是导致内存走漏的另一个常见原因。 确保在利用完天生的材料后烧毁它们。
  1. Material material;
  2. void Awake()
  3. {
  4. material = new Material(); // Dynamically generated material
  5. }
  6. void OnDestroy()
  7. {
  8. if (material != null)
  9. {
  10. Destroy(material); // Destroying a material when you have finished using it
  11. }
  12. }
复制代码
材料应该在利用完后烧毁(OnDestroy)。
根据项目标规则和规范,在适当的时间烧毁材料。
如果项目中无法避免new材质球,可以利用对象池管理材质球
利用材质属性快来替换Material属性操纵
通过MaterialPropertyBlock的方式来进行优化
      
详细相关操纵和例子见如下文章《利用MaterialPropertyBlock来替换Material属性操纵》。不过这种方法在URP下不实用,会打断SRP Batcher。

            
材质属性块被用于Graphics.DrawMesh和Renderer.SetPropertyBlock两个API,当我们想要绘制很多雷同材质但不同属性的对象时可以利用它。例如你想改变每个绘制网格的颜色,但是它却不会改变渲染器的状态。

   
  1. colorID = Shader.PropertyToID("_Color");
  2.         prop = new MaterialPropertyBlock();
  3.         
  4.          listProp[i].GetComponent<Renderer>().GetPropertyBlock(prop);
  5. prop.SetColor(colorID, new Color(r, g, b, 1));
  6.                 listProp[i].GetComponent<Renderer>().SetPropertyBlock(prop);   
复制代码
   

               
同时我也通过Profiler的Memory模块,切换进Detailed选项,对其进行采样,可以发现在Sence Memory下面会有Material的拷贝(材质操纵导致,而材质属性操纵不会)。这也验证了操纵材质时会有实例化存在,而利用材质属性块则不存在实例化。

   

   

    今天是2024年12月1日

重复一段毒鸡汤来勉励我和你
你的对手在看书
你的对头在磨刀
你的闺蜜在减肥
隔壁的老王在练腰
而你在干嘛?
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表