Unity文档——AssetBundle使用模式

AssetBundle使用模式

版本检查:2017.3

-

难度:高级

 

这是关于Unity 5中资产,资源和资源管理系列文章的第五章。

本系列的前一章介绍了AssetBundles基础知识,其中包括各种加载API的低级行为。本章讨论在实践中使用AssetBundle的各个方面的问题和可能的解决方案。

管理已加载的资产

在内存敏感的环境中仔细控制加载的对象的大小和数量至关重要。从活动场景中删除对象时,Unity不会自动卸载对象。资产清理在特定时间触发,也可以手动触发。

必须谨慎管理AssetBundles本身。由本地存储上的文件(在Unity缓存中或通过AssetBundle.LoadFromFile加载的文件)支持的AssetBundle具有最小的内存开销,很少消耗超过几十千字节。但是,如果存在大量AssetBundle,这种开销仍然会成为问题。

由于大多数项目允许用户重新体验内容(例如重放级别),因此了解何时加载或卸载AssetBundle非常重要。如果AssetBundle未正确卸载,则可能导致内存中的对象重复。不正确地卸载AssetBundles也会在某些情况下导致不良行为,例如导致纹理丢失。要了解为什么会发生这种情况,请参阅“ 资产,对象和序列化”一章的“ 对象间引用”部分。

管理资产和AssetBundle时最重要的一点是,对于unloadAllLoadedObjects参数调用AssetBundle.Unload时,行为的区别在于true或false 。

此API将卸载正在调用的AssetBundle的标头信息。所述unloadAllLoadedObjects参数确定是否还从卸载这个AssetBundle实例化的所有对象。如果设置为true,那么源自AssetBundle的所有对象也将立即卸载 - 即使它们当前正在活动场景中使用。

例如,假设材料M是从AssetBundle AB加载的,并假设M当前处于活动场景中。

描述

如果调用了AssetBundle.Unload(true),则M将从场景中删除,销毁并卸载。但是,如果调用了AssetBundle.Unload(false),那么AB的头信息将被卸载,但是M将保留在场景中并且仍然可以正常工作。调用AssetBundle.Unload(false)会中断MAB之间的链接。如果稍后再次加载AB,则AB中包含的对象的新副本将被加载到内存中。

描述

如果稍后再次加载AB,则将重新加载AssetBundle标头信息的新副本。然而,中号是不是从这个新副本加载AB。Unity不会在ABM的新副本之间建立任何链接。

描述

如果调用AssetBundle.LoadAsset()来重新加载M,Unity将不会将M的旧副本解释为AB中的数据实例。因此,Unity将加载M的新副本,并且场景中将有两个相同的M副本。

描述

对于大多数项目,这种行为是不可取的。大多数项目应该使用AssetBundle.Unload(true)并采用一种方法来确保对象不会重复。两种常用方法是:

  1. 在应用程序的生命周期中,在卸载瞬态AssetBundle时具有明确定义的点,例如在级别之间或在加载屏幕期间。这是更简单和最常见的选择。

  2. 维护单个对象的引用计数,并仅在所有组成对象未使用时卸载AssetBundle。这允许应用程序卸载和重新加载单个对象,而无需重复内存。

如果应用程序必须使用AssetBundle.Unload(false),则只能以两种方式卸载单个对象:

  1. 消除场景和代码中对不需要的Object的所有引用。完成此操作后,调用Resources.UnloadUnusedAssets

  2. 非加性地加载场景。这将破坏当前场景中的所有对象并自动调用Resources.UnloadUnusedAssets

如果项目具有定义明确的点,用户可以等待对象加载和卸载,例如在游戏模式或级别之间,则应使用这些点来根据需要卸载任意数量的对象并加载新对象。

最简单的方法是将项目的离散块打包到场景中,然后将这些场景及其所有依赖项构建到AssetBundles中。然后,应用程序可以进入“加载”场景,完全卸载包含旧场景的AssetBundle,然后加载包含新场景的AssetBundle。

虽然这是最简单的流程,但有些项目需要更复杂的AssetBundle管理。由于每个项目都不同,因此没有通用的AssetBundle设计模式。

在决定如何将对象分组到AssetBundles时,通常最好先将对象捆绑到AssetBundles中(如果必须同时加载或更新它们)。例如,考虑角色扮演游戏。单个地图和过场动画可以按场景分组到AssetBundles中,但在大多数场景中都需要一些对象。可以构建AssetBundles以提供肖像,游戏内UI以及不同的角色模型和纹理。然后可以将这些后面的对象和资产分组到第二组AssetBundle中,这些AssetBundle在启动时加载并在应用程序的生命周期内保持加载状态。

如果Unity必须在卸载AssetBundle后从其AssetBundle重新加载Object,则可能会出现另一个问题。在这种情况下,重新加载将失败,对象将作为(缺失)对象出现在Unity编辑器的层次结构中。

这主要发生在Unity失去并重新获得对其图形上下文的控制时,例如当移动应用程序被暂停或用户锁定其PC时。在这种情况下,Unity必须将纹理和着色器重新上传到GPU。如果这些资源的源AssetBundle不可用,则应用程序将场景中的对象呈现为洋红色。

4.2。分配

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

是否在安装之内或之后运送AssetBundles的决定是由项目运行的平台的功能和限制驱动的。移动项目通常选择安装后下载以减少初始安装大小,并保持低于无线下载大小限制。控制台和PC项目通常在初始安装时运送AssetBundles。

无论最初如何交付AssetBundle,正确的体系结构都允许在安装后将新的或修订的内容修补到项目中。有关此内容的更多信息,请参阅Unity手册中的“ 使用AssetBundles修补”部分。

4.2.1。装运项目

使用该项目运送AssetBundles是分发它们的最简单方法,因为它不需要额外的下载管理代码。项目可能包含AssetBundles和安装有两个主要原因:

  • 减少项目构建时间并允许更简单的迭代开发。如果这些AssetBundle不需要与应用程序本身分开更新,那么AssetBundle可以通过将AssetBundle存储在Streaming Assets中而包含在应用程序中。请参阅下面的Streaming Assets部分。

  • 发布可更新内容的初始修订版。这通常是为了在最初安装后节省最终用户的时间,或者作为以后修补的基础。流式资产对于这种情况并不理想。但是,如果不能编写自定义下载和缓存系统,则可以从Streaming Assets将可更新内容的初始修订加载到Unity缓存中

4.2.1.1。流媒体资产

在安装时在Unity应用程序中包含任何类型的内容(包括AssetBundle)的最简单方法是在构建项目之前将内容构建到/ Assets / StreamingAssets /文件夹中。构建时StreamingAssets文件夹中包含的任何内容都将复制到最终应用程序中。

可以在运行时通过属性Application.streamingAssetsPath访问本地存储上StreamingAssets文件夹的完整路径。然后可以在大多数平台上通过AssetBundle.LoadFromFile加载AssetBundle

Android开发者:在Android上,StreamingAssets文件夹中的资源存储在APK中,如果压缩它们可能需要更多时间加载,因为存储在APK中的文件可以使用不同的存储算法。所使用的算法可能因Unity版本而异。您可以使用7-zip等存档打开APK以确定文件是否已压缩。如果是,您可以期望AssetBundle.LoadFromFile()执行得更慢。在这种情况下,您可以使用 UnityWebRequest.GetAssetBundle检索缓存版本作为一种解决方法。通过使用UnityWebRequest,AssetBundle将在第一次运行期间解压缩并缓存,从而允许后续执行更快。请注意,这将占用更多存储空间,因为AssetBundle将被复制到缓存中。或者,您可以导出Gradle项目并在构建时向AssetBundles添加扩展。然后,您可以编辑build.gradle文件并将该扩展添加到noCompress部分。完成后,您应该能够使用AssetBundle.LoadFromFile()而无需支付减压性能成本。

注意: Streaming Assets在某些平台上不是可写位置。如果项目的AssetBundles需要在安装后更新,请使用WWW.LoadFromCacheOrDownload或编写自定义下载程序。

4.2.2。下载后安装

向移动设备提供AssetBundles的首选方法是在安装应用程序后下载它们。这还允许在安装后更新内容,而不强制用户重新下载整个应用程序。在许多平台上,应用程序二进制文件必须经过昂贵且冗长的重新认证过程。因此,开发一个良好的安装后下载系统至关重要。

提供AssetBundles的最简单方法是将它们放在Web服务器上并通过UnityWebRequest提供。Unity将自动将下载的AssetBundle缓存在本地存储上。如果下载的AssetBundle是LZMA压缩的,则AssetBundle将作为未压缩或重新压缩存储在缓存中,如LZ4(取决于Caching.compressionEnabled设置),以便将来加载更快。如果下载的包是LZ4压缩的,则AssetBundle将被压缩存储。如果缓存填满,Unity将从缓存中删除最近最少使用的AssetBundle。有关更多详细信息,请参阅内置缓存部分。

通常建议使用来启动UnityWebRequest如果可能,或WWW.LoadFromCacheOrDownload只有使用Unity 5.2或以上。如果内置API的内存消耗,缓存行为或性能对于特定项目是不可接受的,或者项目必须运行特定于平台的代码以实现其要求,则仅投资自定义下载系统。

可能阻止使用UnityWebRequestWWW.LoadFromCacheOrDownload的情况示例

  • 当需要对AssetBundle缓存进行细粒度控制时

  • 当项目需要实现自定义压缩策略时

  • 当项目希望使用特定于平台的API来满足某些要求时,例如在非活动时需要流式传输数据。

    • 示例:使用iOS的后台任务API在后台下载数据。
  • 必须在Unity没有正确SSL支持的平台(例如PC)上通过SSL提供AssetBundle。

4.2.3。内置缓存

Unity有一个内置的AssetBundle缓存系统,可以用来缓存通过UnityWebRequest API 下载的AssetBundles,它有一个重载接受一个AssetBundle版本号作为参数。此数字存储在AssetBundle中,并且不由 AssetBundle系统生成。

缓存系统跟踪传递给UnityWebRequest的最新版本号。当使用版本号调用此API时,缓存系统会通过比较版本号来检查是否存在缓存的AssetBundle。如果这些数字匹配,系统将加载缓存的AssetBundle。如果数字不匹配,或者没有缓存的AssetBundle,则Unity将下载新副本。此新副本将与新版本号相关联。

缓存系统中的AssetBundle仅由其文件名标识,而不是由下载它们的完整URL标识。这意味着具有相同文件名的AssetBundle可以存储在多个不同的位置,例如内容分发网络。只要文件名相同,缓存系统就会将它们识别为相同的AssetBundle。

每个应用程序都可以确定将版本号分配给AssetBundles的适当策略,并将这些数字传递给UnityWebRequest。这些数字可能来自各种类型的唯一标识符,例如CRC值。请注意,虽然AssetBundleManifest.GetAssetBundleHash()也可用于此目的,但我们不建议使用此函数进行版本控制,因为它只提供估算,而不是真正的哈希计算)。

有关详细信息,请参阅Unity手册中的“ 使用AssetBundles修补”部分。

在Unity 2017.1之后,通过允许开发人员从多个缓存中选择活动缓存,缓存了Caching API以提供更精细的控制。Unity的早期版本可能只修改Caching.expirationDelayCaching.maximumAvailableDiskSpace以删除缓存的项目(这些属性保留在Cache类中的Unity 2017.1中)。

expirationDelay是自动删除AssetBundle之前必须经过的最小秒数。如果在此期间未访问AssetBundle,则会自动删除它。

maximumAvailableDiskSpace指定缓存在开始删除比expirationDelay最近使用的AssetBundle之前可能使用的本地存储空间量(以字节为单位)。达到限制时,Unity将删除最近最少打开的缓存中的AssetBundle(或标记为通过Caching.MarkAsUsed使用)。Unity将删除缓存的AssetBundle,直到有足够的空间来完成新的下载。

4.2.3.1。缓存启动

由于AssetBundles由其文件名标识,因此可以使用随应用程序提供的AssetBundle“填充”缓存。为此,请将每个AssetBundle的初始版本或基本版本存储在/ Assets / StreamingAssets /中。该过程与Shipped with project部分中详述的过程相同。

可以通过在第一次运行应用程序时从Application.streamingAssetsPath加载AssetBundle来填充缓存。从那时起,应用程序可以正常调用UnityWebRequest(UnityWebRequest也可以用于从StreamingAssets路径初始加载AssetBundle)。

4.2.3。自定义下载程序

编写自定义下载程序使应用程序可以完全控制AssetBundles的下载,解压缩和存储方式。由于涉及的工程工作非常重要,我们建议这种方法仅适用于大型团队。编写自定义下载程序时有四个主要注意事项:

  • 下载机制

  • 存储位置

  • 压缩类型

  • 修补

有关修补AssetBundles的信息,请参阅使用AssetBundles修补部分。

4.2.3.1。下载

对于大多数应用程序,HTTP是下载AssetBundles的最简单方法。但是,实现基于HTTP的下载器并不是最简单的任务。自定义下载程序必须避免过多的内存分配,过多的线程使用和过多的线程唤醒。Unity的WWW类不适用于此处详尽描述的原因。

编写自定义下载程序时,有三个选项:

  • C#的HttpWebRequest和WebClient类

  • 自定义本机插件

  • 资产商店包

4.2.3.1.1。C#类

如果应用程序不需要HTTPS / SSL支持,C#的WebClient类提供了最简单的下载AssetBundle的机制。它能够将任何文件异步下载到本地存储,而无需过多的托管内存分配。

要使用WebClient下载AssetBundle,请分配该类的实例,并将要下载的AssetBundle的URL和目标路径传递给它。如果需要对请求的参数进行更多控制,则可以使用C#的HttpWebRequest类编写下载程序:

  1. HttpWebResponse.GetResponseStream获取字节流。

  2. 在堆栈上分配固定大小的字节缓冲区。

  3. 从响应流读入缓冲区。

  4. 使用C#的File.IO API或任何其他流式IO系统将缓冲区写入磁盘。

4.2.3.1.2。资产商店包

多个资产商店包提供本机代码实现,以通过HTTP,HTTPS和其他协议下载文件。在为Unity编写自定义本机代码插件之前,建议您评估可用的Asset Store软件包。

4.2.3.1.3。自定义本机插件

编写自定义本机插件是最耗时但最灵活的在Unity中下载数据的方法。由于编程时间要求高,技术风险高,只有在没有其他方法能够满足应用要求的情况下才推荐使用此方法。例如,如果应用程序必须在Unity中没有C#SSL支持的平台上使用SSL通信,则可能需要自定义本机插件。

自定义本机插件通常会包装目标平台的本机下载API。示例包括iOS 上的NSURLConnection和Android 上的java.net.HttpURLConnection。有关使用这些API的更多详细信息,请参阅每个平台的本机文档。

4.2.3.2。存储

在所有平台上,Application.persistentDataPath都指向一个可写位置,该位置应该用于存储应在应用程序运行之间保留的数据。编写自定义下载程序时,强烈建议使用Application.persistentDataPath的子目录来存储下载的数据。

Application.streamingAssetPath不可写,对于AssetBundle缓存来说是一个糟糕的选择。streamingAssetsPath的示例位置包括:

  • OSX:在.app包中; 不可写

  • Windows:在安装目录中(例如Program Files); 通常不可写

  • iOS:在.ipa包内; 不可写

  • Android:在.apk文件中; 不可写

4.3。资产分配策略

决定如何将项目的资产划分为AssetBundle并不简单。采用简单的策略是很诱人的,例如将所有对象放在他们自己的AssetBundle中或只使用一个AssetBundle,但这些解决方案有明显的缺点:

  • 资产捆绑太少......

    • 增加运行时内存使用量

    • 增加加载时间

    • 需要更大的下载量

  • 拥有太多AssetBundles ......

    • 增加构建时间

    • 可以使开发复杂化

    • 增加总下载时间

关键决定是如何将对象分组为AssetBundles。主要策略是:

  • 逻辑实体

  • 对象类型

  • 并发内容

有关这些分组策略的更多信息,请参见手册

4.4。常见的陷阱

本节介绍使用AssetBundle的项目中常见的几个问题。

4.5.1。资产重复

当Object被构建到AssetBundle中时,Unity 5的AssetBundle系统将发现Object的所有依赖关系。此依赖关系信息用于确定将包含在AssetBundle中的对象集。

明确分配给AssetBundle的对象将仅构建到该AssetBundle中。当Object的AssetImporter将其assetBundleName属性设置为非空字符串时,“显式指定”Object 。这可以通过在Object的Inspector中选择AssetBundle或从Editor脚本在Unity Editor中完成。

通过将对象定义为AssetBundle构建映射的一部分,也可以将对象分配给AssetBundle ,该映射将与重载的BuildPipeline.BuildAssetBundles()函数一起使用,该函数接收AssetBundleBuild数组。

未在AssetBundle中显式分配的任何Object将包含在包含一个或多个引用未标记对象的对象的所有AssetBundle中。

例如,如果将两个不同的对象分配给两个不同的AssetBundle,但两者都引用了公共依赖项Object,那么该依赖项Object将被复制到两个AssetBundle中。重复的依赖项也将被实例化,这意味着依赖项Object的两个副本将被视为具有不同标识符的不同对象。这将增加应用程序的AssetBundles的总大小。如果应用程序加载其父项,则还会导致将两个不同的Object副本加载到内存中。

有几种方法可以解决这个问题:

  1. 确保内置于不同AssetBundle的对象不共享依赖项。任何共享依赖项的对象都可以放在同一个AssetBundle中,而不会复制它们的依赖项。

    • 对于具有许多共享依赖项的项目,此方法通常不可行。它生成单片AssetBundle,必须经常重建和重新下载才能方便或高效。
  2. 对AssetBundles进行分段,以便不会同时加载共享依赖关系的两个AssetBundle。

    • 此方法可能适用于某些类型的项目,例如基于级别的游戏。但是,它仍然不必要地增加了项目的AssetBundles的大小,并增加了构建时间和加载时间。
  3. 确保所有依赖项资产都内置在自己的AssetBundle中。这完全消除了重复资产的风险,但也带来了复杂性。应用程序必须跟踪AssetBundle之间的依赖关系,并确保在调用任何AssetBundle.LoadAsset API 之前加载了正确的AssetBundle 。

通过位于UnityEditor命名空间中的AssetDatabase API 跟踪对象依赖。正如命名空间所暗示的,此API仅在Unity编辑器中可用,而不是在运行时。AssetDatabase.GetDependencies可用于查找特定对象或资产的所有直接依赖项。请注意,这些依赖项可能有自己的依赖项。此外,AssetImporter API可用于查询分配了任何特定Object的AssetBundle。

通过组合AssetDatabaseAssetImporter API,可以编写一个Editor脚本,确保将所有AssetBundle的直接或间接依赖项分配给AssetBundle,或者没有两个AssetBundle共享尚未分配给AssetBundle的依赖项。由于复制资产的内存成本,建议所有项目都有这样的脚本。

4.5.2。精灵地图集重复

任何自动生成的精灵地图集都将分配给包含从中生成精灵地图集的精灵对象的AssetBundle。如果精灵对象被分配给多个AssetBundle,则精灵地图集将不会被分配给AssetBundle并且将被复制。如果Sprite对象未分配给AssetBundle,则sprite图集也不会分配给AssetBundle。

为了确保精灵地图集不重复,请检查标记到相同精灵地图集的所有精灵都被分配到同一个AssetBundle。

请注意,在Unity 5.2.2p3及更早版本中,永远不会将自动生成的精灵地图集分配给AssetBundle。因此,它们将被包含在任何包含其组成精灵的AssetBundle中,以及任何引用其组成精灵的AssetBundles。由于这个问题,强烈建议使用Unity的sprite packer的所有Unity 5项目升级到Unity 5.2.2p4,5.3或任何更新版本的Unity。

4.5.3。Android纹理

由于Android生态系统中存在大量设备碎片,因此通常需要将纹理压缩为多种不同的格式。虽然所有Android设备都支持ETC1,但ETC1不支持具有Alpha通道的纹理。如果应用程序不需要OpenGL ES 2支持,解决问题的最简单方法是使用所有Android OpenGL ES 3设备都支持的ETC2。

大多数应用程序需要在ETC2支持不可用的旧设备上发布。解决此问题的一种方法是使用Unity 5的AssetBundle Variants(有关其他选项的详细信息,请参阅Unity的Android优化指南)。

要使用AssetBundle变量,必须将使用ETC1无法完全压缩的所有纹理分离为仅纹理的AssetBundle。接下来,使用特定于供应商的纹理压缩格式(如DXT5,PVRTC和ATITC),创建这些AssetBundle的足够变体,以支持Android系统中不支持ETC2的切片。对于每个AssetBundle Variant,将包含的纹理的TextureImporter设置更改为适合Variant的压缩格式。

在运行时,可以使用SystemInfo.SupportsTextureFormat API 检测对不同纹理压缩格式的支持。此信息应用于选择和加载包含以受支持格式压缩的纹理的AssetBundle Variant。

有关Android纹理压缩格式的更多信息,请访问此处

4.5.4。iOS文件处理过度使用

当前版本的Unity不受此问题的影响。

在Unity 5.3.2p2之前的版本中,Unity将在AssetBundle加载的整个时间内保存一个打开的文件句柄。这在大多数平台上都不是问题。但是,iOS限制进程可能同时打开255的文件句柄数。如果加载AssetBundle导致超出此限制,则加载调用将失败,并显示“Too Many Open File Handles”错误。

对于试图将内容划分为数百或数千个AssetBundle的项目而言,这是一个常见问题。

对于无法升级到修补版Unity的项目,临时解决方案是:

  • 通过合并相关的AssetBundle减少正在使用的AssetBundle数量

  • 使用AssetBundle.Unload(false)关闭AssetBundle的文件句柄,并手动管理加载的对象的生命周期

4.5。AssetBundle Variants

AssetBundle系统的一个关键特性是引入了AssetBundle Variants。Variants的目的是允许应用程序调整其内容以更好地适应其运行时环境。变量允许不同AssetBundle文件中的不同UnityEngine.Object在加载对象和解析实例ID引用时显示为“相同”对象。从概念上讲,它允许两个UnityEngine.Objects共享相同的文件GUID和本地ID,并通过字符串Variant ID标识要加载的实际UnityEngine.Object。

该系统有两个主要用例:

  1. 变体简化了适用于给定平台的AssetBundle的加载。

    • 示例:构建系统可能会创建一个AssetBundle,其中包含适用于独立DirectX11 Windows构建的高分辨率纹理和复杂着色器,以及第二个具有适用于Android的低保真内容的AssetBundle。在运行时,项目的资源加载代码可以为其平台加载适当的AssetBundle Variant,而传递给AssetBundle.Load API的Object名称不需要更改。
  2. 变体允许应用程序在同一平台上加载不同的内容,但使用不同的硬件。

    • 这是支持各种移动设备的关键。iPhone 4无法在任何实际应用程序中显示与最新iPhone相同的内容保真度。

    • 在Android上,AssetBundle Variants可用于解决设备之间屏幕宽高比和DPI的巨大碎片问题。

4.5.1。限制

AssetBundle Variant系统的一个关键限制是它要求Variants从不同的Assets构建。即使这些资产之间的唯一差异是其导入设置,此限制也适用。如果构建到变体A和变体B中的纹理之间的唯一区别是在Unity纹理导入器中选择的特定纹理压缩算法,则变体A和变体B必须仍然是完全不同的资产。这意味着Variant A和Variant B必须是磁盘上的单独文件。

此限制使大型项目的管理变得复杂,因为特定资产的多个副本必须保留在源代码管理中。当开发人员希望更改资产的内容时,必须更新资产的所有副本。此问题没有内置的解决方法。

大多数团队都实施自己的AssetBundle Variants形式。这是通过构建AssetBundles来实现的,并在其文件名后附加明确定义的后缀,以便识别给定AssetBundle所代表的特定变体。在构建这些AssetBundle时,自定义代码以编程方式更改包含的Assets的导入器设置。一些开发人员已经扩展了他们的自定义系统,以便能够更改附加到预制件的组件上的参数。

4.6。压缩还是未压缩?

是否压缩AssetBundles需要考虑几个重要因素,其中包括:

  • 加载时间:从本地存储或本地缓存加载时,未压缩的AssetBundle加载速度比压缩的AssetBundle快得多。

  • 构建时间:LZMA和LZ4在压缩文件时非常慢,Unity Editor按顺序处理AssetBundles。具有大量AssetBundle的项目将花费大量时间来压缩它们。

  • 应用程序大小:如果AssetBundle在应用程序中提供,压缩它们将减少应用程序的总大小。或者,可以在安装后下载AssetBundles。

  • 内存使用:在Unity 5.3之前,所有Unity的解压缩机制都需要在解压缩之前将整个压缩的AssetBundle加载到内存中。如果内存使用很重要,请使用未压缩或LZ4压缩的AssetBundle。

  • 下载时间:仅当AssetBundle很大,或者用户处于带宽受限的环境中时(例如在低速或计量连接上下载),才可能需要压缩。如果在高速连接上仅向PC传送几十兆字节的数据,则可以省略压缩。

4.6.1。紧缩压缩

主要由DXT压缩纹理组成的捆绑包使用Crunch压缩算法应该是未压缩的。

4.7。AssetBundles和WebGL

Unity强烈建议开发人员不要在WebGL项目上使用压缩的AssetBundle。

WebGL项目中的所有AssetBundle解压缩和加载必须在主线程上进行。这是因为Unity的WebGL导出选项目前不支持工作线程。使用XMLHttpRequest将AssetBundles的下载委托给浏览器,XMLHttpRequest在Unity的主线程上执行。这意味着在WebGL上加载压缩的AssetBundle非常昂贵。

如果您使用的是Unity 5.5或更早版本,请考虑为您的AssetBundle避免使用LZMA,而使用LZ4进行压缩,这可以按需非常有效地解压缩。如果您需要更小的压缩大小(LZ4),您可以将Web服务器配置为在HTTP协议级别上压缩文件(在LZ4压缩之上)。Unity 5.6删除了LZMA作为WebGL平台的压缩选项。

猜你喜欢

转载自blog.csdn.net/zhaoguanghui2012/article/details/81225957