美文网首页
Unity中关于AssetBundle和Resources的教程

Unity中关于AssetBundle和Resources的教程

作者: Francis_Rose | 来源:发表于2020-06-08 11:23 被阅读0次

    教程地址:https://learn.unity.com/tutorial/assets-resources-and-assetbundles#5c7f8528edbc2a002053b5a9

    AssetBundle和Resources的内容主要包括4个方面:

    1. Assets(资产),Objects(对象)和serialization(序列化),主要包含Unity如何序列化Assets并处理Assets间的相互引用;
    2. Resources目录,内置的Resources的API;
    3. AssetBundle基础,如何操作AssetBundle,如何加载AssetBundle以及从AssetBundle中加载Assets;
    4. AssetBundle的使用模式,分配Assets到AssetBundle,如何管理加载的Assets。
    • Assets(资产),Objects(对象)和serialization(序列化)
      适当的Asset管理对快速加载和内存的少量使用非常重要,首先要先区分Assets和Objects
    1. Assets和Objects内部
      弄懂Unity标识和序列化数据的首要关键点是区分Assets和UnityEngine.Objects

      • Asset是硬盘中的文件,存储在Unity工程中的Assets目录下。比如Textures(纹理),3D模型,或者声音片段等。
      • UnityEngine.Object是一组序列化数据,共同描述特定的资源实例。如mesh(网格),sprite等。
        还有两种特殊的Object类型:ScriptableObject和MonoBehaviour
    2. 对象间引用
      所有UnityEngine.Objects都可以引用其他UnityEngine.Objects。 这些其他对象可以驻留在同一资产文件中,也可以从其他资产文件中导入。
      例如,一个材质对象通常具有一个或多个对纹理对象的引用。

      Unity使用File GUID和Local ID来辅助序列化,File GUID标识存储目标资源的资产文件,本地唯一的Local ID标识
      资产文件中的每个对象。其中File GUID存储在.meta文件中。

    3. 为什么需要File GUID和Local ID
      为了健壮性并提供灵活、平台无关的工作流程.File GUID提供了文件特定位置的抽象。 只要可以将特定的文件GUID与特定的
      文件相关联,该文件在磁盘上的位置就变得无关紧要。 可以自由移动文件,而不必更新引用该文件的所有对象。

      如果与Asset文件管理的File GUID丢失了,那么资产文件中所有对象的引用也将丢失。 这就是为什么.meta文件必须保持与其关联
      的Asset文件使用相同的文件名和相同文件夹存储的原因。

      Unity编辑器具有特定文件路径到已知文件GUID的映射。 每当加载或导入资产时,都会记录地图条目。
      映射条目将资产的特定路径链接到资产的文件GUID。

    4. 复杂Asset和导入
      Unity可以支持导入非本地资源,如FBX等,这些可以通过AssetImporter的API来处理。导入过程会将源Asset转换
      为适合目标平台的格式。此过程适用于所有资产,而不仅仅是非本地资产。本地资产不需要冗长的转换过程或重新序列化。

    5. 序列化和实例
      尽管File GUID和Local ID是健壮的,但GUID比较缓慢,并且在运行时需要性能更高的系统。 Unity在内部维护一个高速缓存,
      该高速缓存将File GUID和Local ID转换为简单的,会话唯一的整数。这些整数称为Instance ID,并以简单的,
      单调递增的顺序分配在缓存中注册新对象时。

      高速缓存维护给定实例ID,File GUID和Local ID之间的映射,这些映射定义了对象的源数据的位置以及对象在内存中的实例
      (如果有)。这使UnityEngine.Objects能够可靠地维护彼此之间的引用。解析实例ID引用可以快速返回由实例ID表示的已加载对象。
      如果尚未加载目标对象,则可以将File GUID和Local ID解析为对象的源数据,从而允许Unity即时加载对象。

    6. 加载大层次结构
      当序列化Unity GameObjects的层次结构时,例如在预制序列化过程中,重要的是要记住整个层次结构将被完全序列化。
      也就是说,层次结构中的每个GameObject和Component将在序列化数据中单独表示。这对加载和实例化GameObjects层次结构所需的
      时间产生了有趣的影响。
      创建任何GameObject层次结构时,CPU时间会以几种不同的方式花费:
      a. 读取源数据(从存储,从AssetBundle,从另一个GameObject等)
      b. 在新的变换之间设置父子关系
      c. 实例化新的GameObjects和组件
      d. 在主线程上唤醒新的GameObjects和Components

      从内存中读取数据要比从存储设备加载数据快的多,从存储设备加载数据的I/O操作就很费时。所以预制件的大小就需要把握好,因为
      整个对象都被序列化,加载速度就很受影响了。所以一定要使用多层次结构的prefab,可以将其分块,然后运行时缝合起来。

    • 资源目录
    1. 最佳实践
      最好是不使用,因为:
      a. 使用Resources文件夹会使更细粒度的内存管理更加困难
      b. 资源文件夹使用不当会增加应用程序的启动时间和构建时间,随着“资源”文件夹的数量增加,在这些文件夹中管理资产变得非常困难
      c. 资源系统降低了项目向特定平台交付自定义内容的能力,并消除了增量内容升级的可能性,AssetBundle Variants是Unity的主要工具,用于按设备调整内容

    2. 适当的使用
      某些情况下,还是需要使用Resource的,比如需要三方配置数据等,不需要patch的内容等

    3. Resource的序列化
      项目构建时,Resources中的Assets和Objects会合并到一个序列化文件中,包含元数据和索引信息,类似于AssetBundle。这样,在内部就
      需要构建查找结构,内部使用平衡搜索树,在splash播放的时候发生,这就需要消耗了。

    • AssetBundle基础
    1. 布局
      AssetBundle包含两个部分:头部和数据段。

    2. 加载AssetBundle
      通过提供的API加载:
      AssetBundle.LoadFromMemory(Async optional) - Unity不推荐该方式,因为需要使用3倍的字节数据的内存
      AssetBundle.LoadFromFile(Async optional) - 最高效的加载没压缩的数据。
      UnityWebRequest's DownloadHandlerAssetBundle
      WWW.LoadFromCacheOrDownload (on Unity 5.6 or older)

    3. 从AssetBundle加载Assets
      LoadAsset (LoadAssetAsync)
      LoadAllAssets (LoadAllAssetsAsync)
      LoadAssetWithSubAssets (LoadAssetWithSubAssetsAsync)

    4. AssetBundle的依赖
      Unity根据运行时环境使用两个不同的API来自动跟踪AssetBundle间的依赖。Editor下使用AssetDatabase的API查询依赖。
      AssetImporter的API可以访问和修改AssetBundle的分配和依赖。在运行时,Unity提供了一个可选API,
      以通过基于ScriptableObject的AssetBundleManifest API加载在AssetBundle构建期间生成的依赖项信息。

      当执行BuilePipeline.BuildAssetBundles的时候,Unity会序列化包含依赖信息的对象,然后单独存储,依据
      AssetBundleManifest类型。文件名与文件夹名相同。

    • AssetBundle使用模式
    1. 管理加载的Asset
      对于内存敏感的环境下,小心控制加载对象的大小和数量就非常重要了。Unity并不会在对象被移除的时候自动卸载它们。
      Asset的清理在特定时间触发,也可以手动触发。AssetBundle卸载如果不正确,会造成在对象在内存中的重复。

      AssetBundle的卸载通过AssetBundle.Unload(ture/false),当参数为true时会强制卸载所有,即便还有引用。参数为false时,
      只是将AssetBundle与Object(对象)的引用链接断开,下次加载时,不会重新建立链接,这样就造成了内存中的重复对象。

    2. 分发
      将项目的AssetBundle分发给客户端有两种基本方法:与项目同时安装它们或在安装后下载它们。

    相关文章

      网友评论

          本文标题:Unity中关于AssetBundle和Resources的教程

          本文链接:https://www.haomeiwen.com/subject/wexzzhtx.html