zoukankan      html  css  js  c++  java
  • Unity3D性能优化之资源原理科普篇

    一、Unity的资源(Asset)和对象(UnityEngine.Objects)

    资源(Asset)是硬盘中的文件,存储在Unity工程的Assets文件夹内。例如,纹理(Texture),材质(Material)和FBX文件等,它们都是资源。一些资源的数据格式是Unity原生支持的,例如材质。有些资源则需要转换为原生的数据格式后才能被Unity使用,例如FBX文件。
    对象(UnityEngine.Object)代表序列化数据的集合,表示某个资源的具体实例。它可以是Unity引擎使用的任何类型的资源,例如网格,Sprite,音频剪辑或动画剪辑。所有的对象(Object)都是UnityEngine.Object基类的子类。

    几乎所有的对象(Object)类型都是内建的,其中有两种比较特殊的类型。

    ScriptableObject为开发者提供了一套便捷的系统,供开发者自定义数据类型。这些类型可以被Unity直接序列化或反序列化,并在Unity编辑器的检视器窗口中进行操作。
    MonoBehaviour提供了链接MonoScript的容器。MonoScript是一种内部数据类型,Unity用它保存对某个特定程序集和命名空间中特定脚本类的引用,MonoScript本身不包含任何实际的可执行代码。

    资源(Asset)与对象(Object)是一种一对多的关系,即一个资源文件可能会包括多个Object。

    二、对象之间的引用

    所有UnityEngine.Objects都可以引用其他的UnityEngine.Objects。这里“其他的Object”可能存在于相同的资源文件中,或需要从其他资源文件导入。例如,一个材质Object通常有一个或多个纹理Object的引用。这些纹理Object一般是从一个或多个纹理资源文件中导入的(例如PNG或JPG文件)。

    序列化后,这些引用由两部分数据组成:文件GUID和本地ID。文件GUID用于识别资源(Asset)文件中目标资源(Resource)的存储位置。而本地唯一的ID负责识别单个资源文件中的Object,因为一个资源文件可能会包含多个Object。

    比如一个特效做成的Prefab,直接用文本打开prefab和prefab.meta后缀的两个文件。

    GUID:存储于.meta文件中。Unity会在首次导入资源文件时生成.meta文件,并和资源文件一起存储在相同的目录中。GUID提供了文件存储位置的抽象,这样一个文件GUID就对应一个具体的文件,因此我们才能随意移动这个文件而不破坏所有相关Object对这个文件的引用。

    fileFormatVersion: 2
    guid: 87160fe309c6cd4458c5f56188b57684
    timeCreated: 1568165766
    licenseType: Pro
    NativeFormatImporter:
      externalObjects: {}
      mainObjectFileID: 100100000
      userData: 
      assetBundleName: 
      assetBundleVariant: 
    

    本地ID:是唯一的,使用文本编辑器打开prefab文件,可以看下关于这个预设的所有属性都在配置里面,100100000就是本地ID。任何资源(Asset)文件中都可能含有(或通过导入产生)多个UnityEngine.Object资源(Resource),因此需要一个本地ID来对其中的Object做明确区分。一个大的预设里面会有多个gameobject,相当于总的预设会记录子物体的本地ID,这样才能关联到每一个子物体。

    %YAML 1.1
    %TAG !u! tag:unity3d.com,2011:
    --- !u!1001 &100100000
    Prefab:
      m_ObjectHideFlags: 1
      serializedVersion: 2
      m_Modification:
        m_TransformParent: {fileID: 0}
        m_Modifications: []
        m_RemovedComponents: []
      m_ParentPrefab: {fileID: 0}
      m_RootGameObject: {fileID: 1891991147743598}
      m_IsPrefabParent: 1
    --- !u!1 &1053155390742798
    

    总结:Guid相当于指向一个资源路径;本地ID相当于指向于具体的游戏对象Object

    三、资源引用分析

    我们知道了资源和对象的关系后,对资源引用过程已经清楚了。那么怎么分析资源的引用关系呢?

    AssetDatabase.AssetPathToGUID(path)
    
    AssetDatabase.GUIDToAssetPath(guid)
    

    看代码就大概了解,这两个方法可以将guid和path进行互相转换,因此可以根据预设里引用到的所有guid值,进而可以找到这个资源所引用到对象。

    四、Unity资源引用的机制

    我们在Unity如果创建一个Materials,然后指定一个有两张图片属性的Shader,接着引用了两张纹理。这时候打开材质可以看到是有引用到两个纹理m_Texture。可以看下原先的属性:

    %YAML 1.1
    %TAG !u! tag:unity3d.com,2011:
    --- !u!21 &2100000
    Material:
      serializedVersion: 6
      m_ObjectHideFlags: 0
      m_PrefabParentObject: {fileID: 0}
      m_PrefabInternal: {fileID: 0}
      m_Name: 5400_fangkuai
      m_Shader: {fileID: 4800000, guid: b5f72fe4d91f50b47920a7498eeaf32a, type: 3}
      m_ShaderKeywords: 
      m_LightmapFlags: 4
      m_EnableInstancingVariants: 0
      m_DoubleSidedGI: 0
      m_CustomRenderQueue: -1
      stringTagMap: {}
      disabledShaderPasses: []
      m_SavedProperties:
        serializedVersion: 3
        m_TexEnvs:
        - _AmitTex:
            m_Texture: {fileID: 2800000, guid: 35a133778d8d5f64788367aa21dd2589, type: 3}
            m_Scale: {x: 0.5, y: 1}
            m_Offset: {x: 0, y: 0}
        - _FlowTex:
            m_Texture: {fileID: 2800000, guid: 4cccfa2e1ba52a342b545da00de76a29, type: 3}
            m_Scale: {x: -2, y: -2}
            m_Offset: {x: 0, y: 0}
        m_Floats:
        - _AmitIntensity: 2
        - _FlowIntensity: 4
        - _FlowTexUSpeed: 0.5
        - _FlowTexVSpeed: -0.8
        m_Colors:
        - _Color: {r: 0.32352942, g: 0.5521299, b: 1, a: 1}
        - _FlowColor: {r: 0, g: 0.28539556, b: 0.61764705, a: 1}
    

    如果这时我改一下Shader,而且这个Shader只引用一张纹理,我不赋值。这个材质引用的纹理就变成了三张,前面Shader引用到的纹理依旧在引用。

    m_TexEnvs:
        - _AmitTex:
            m_Texture: {fileID: 2800000, guid: 35a133778d8d5f64788367aa21dd2589, type: 3}
            m_Scale: {x: 0.5, y: 1}
            m_Offset: {x: 0, y: 0}
        - _Amitex:
            m_Texture: {fileID: 0}
            m_Scale: {x: 1, y: 1}
            m_Offset: {x: 0, y: 0}
        - _FlowTex:
            m_Texture: {fileID: 2800000, guid: 4cccfa2e1ba52a342b545da00de76a29, type: 3}
            m_Scale: {x: -2, y: -2}
            m_Offset: {x: 0, y: 0}
    

    总结:这个引用机制就是每次改变时,只增加新的引用,旧的引用不会去删除。

    这个机制的好处:是当又改成之前的shader时,会自动引用到纹理和设置属性。

    这个机制的坏处:资源会导致冗余,打包时会打到多余的资源对象,加载时也会加载多余的资源对象。

    五、Unity资源冗余

    我们知道了引用机制,那么可以发现一些应该避免和注意的问题。

    • 当有对象被删除时,引用此对象的依赖依然存在,应该处理。
    • 材质:材质会引用纹理,而纹理是根据材质所引用的Shader决定,所以应该针对所有材质进行处理纹理的引用。
    • 粒子系统(Particle System):粒子系统可以引用FBX和材质,在Renderer中可以引用到FBX网格,这部分也会引起FBX和纹理引用冗余。

    六、资源打包冗余

    打包冗余是指相同的对象,比如纹理被重复打进多个AB包,这样会造成包体变大,加载重复资源的问题。

    所以我们应该根据这些特性或者说机制,来分析资源引用的关系,再来进行引用的优化。所以针对这种情况会不同的资源先进行分析,最后再根据分析的情况来进行优化。

  • 相关阅读:
    Python动态展示遗传算法求解TSP旅行商问题
    MOEAD算法中均匀权向量的实现---Python
    HDU 5294 多校第一场1007题 最短路+最小割
    POJ 3261 Milk Patterns sa+二分
    HDU 4292 FOOD 2012 ACM/ICPC Asia Regional Chengdu Online
    CodeForces 201A Clear Symmetry
    POJ 1679 The Unique MST 确定MST是否唯一
    POJ 3268 Silver Cow Party 最短路 基础题
    POJ 2139 SIx Degrees of Cowvin Bacon 最短路 水題
    POJ2229 Sumsets 基礎DP
  • 原文地址:https://www.cnblogs.com/wwhhgg/p/12937944.html
Copyright © 2011-2022 走看看