Unity AssetBundles and Resources指引 (三) AssetBundle基础

Unity AssetBundles and Resources指引 (二) Resources文件夹

本文内容主要翻译自下面这篇文章

https://unity3d.com/cn/learn/tutorials/topics/best-practices/guide-assetbundles-and-resources?playlist=30089  A guide to AssetBundles and Resources

第三部分 AssetBundle基础

3.1概览

AssetBundles系统提供一种手段把一个或多个Asset文件归档并能够被unity索引。目的就是分发能这些能够兼容unity序列化系统的数据,是安装后用来更新非代码内容的主要工具。使得能够减少安装包的尺寸和运行时内存压力。以及根据终端设备可选加载优化内容称为可行。

理解AssetBundle工作流程是构建成功的Unity移动设备项目的关键。

3.2 什么是AssetBundle

一个AssetBundle包含两个部分:头部和数据部分。

头部是在构建AssetBundle时unity生成的。存放AssetBundle的信息,比如AssetBundle标记,AssetBundle是否压缩和一分清单。清单是有Object的名字作为索引的查找表。每个查找项提供一个给定名字的Object在数据段位置的字节索引。数据段包含所有Assets的序列化后的原始数据。如果数据段是压缩的。LZMA是整个数据段进行压缩的。即先把所有的Assets序列化,然后把整个字节流进行压缩。

unity5.3之前,AssetBundle内部不能单个Object压缩。如果是使用5.3之前的版本,如果要读取一个或者多个Obect,Unity就要解压整个AssetBundle。一般来说unity会缓存未压缩的版本来提高以后的加载效率。

5.3加入了LZ4压缩选型。用LZ4选项构造的AssetBundle会以单个Object为单位进行压缩。是的加载单个Object不用解压整个AssetBundle。

3.3 AssetBundle管理器

Unity开发了一个AssetBundle的开源参考实现,可以从https://bitbucket.org/Unity-Technologies/assetbundledemo下载。

3.4 加载AssetBundle

在Unity5里面,AssetBundle可以通过4个API加载AssetBundle。这四个api会随着以下两个情况行为有所不同

  1. AssetBundle是LZMA压缩还是LZ4压缩或者是未压缩的
  2. 加载AssetBundle的平台

这四个Api分别是 AssetBundle.LoadFromMemoryAsync、 LoadFromFile、

LoadFromCacheOrDownLoad 和UnityWebRequest的DownloadHandlerAssetBundle。

3.4.1 LoadFromMemoryAsync

Unity建议不要用这个API。在5.3.2之前这个API名字叫CreateFromMemory。名字不一样但是功能一样。

这个方法从托管字节数组里面加载AssetBundle。他总是先将托管字节数组拷贝成本体字节数组。如果是LZMA压缩的,拷贝的时候就进行了解压。如果没压缩在原样拷贝。

这个api至少需要两倍的AssetBundle的尺寸内存。从AssetBundle里面加载的Asset会在内存里面拷贝3次:一次托管字节数组,一次本地内存拷贝还有一次就是Asset自身子啊GPU或者系统内存占用。

3.4.2 LoadFromFile

5.2之前叫CreateFromFile,名字不一样,但是功能是一样的。

如果是加载一个未压缩的AssetBundle,这api十分高效。如果是未压缩或者LZ4压缩,api行为如下:

移动设备上API只加载头信息。只要在Load一个Object才会去加载特定的对象。不会浪费别的内存。

在编辑器里面会加载整个AssetBundle进内存。

注意在安卓设备上,如果版本是5.3或者更老的版本,从StreamAssts目录加载会失败。因为这些内容在一个压缩的jar包里面。5.4后面修复了这个bug。

3.4.3 LoadFromCacheOrDownLoad

如果是从远程服务器上加载资源这是一个有用的api。如果是从本地文件系统加载可以用file://URL形式。如果内容已经存在本地缓存。这个api就和LoadFromFile一样。

如果没有缓存,就会从源处读取内容,如果是压缩的,他会用一个工作线程解压然后写进缓存。一旦缓存,则是未压缩的AssetBundle。

3.4.4 AssetBundleDownLoadHandler

5.3后为移动平台引进的api。比WWW更具弹性。允许开发者指定如果处理下载的数据以便消除不必要的内存消耗。

3..4.5 建议

一般来说,尽量使用LoadFromFile API。他更有效速度更快。如果需要从远程下载资源,5.3或更新的版本建议用UnityWebRequest,老的版本用WWW。

3.5 从AssetBundle加载Asset

可以用三个不同的api从AssetBundle加载Object:LoadAsset、LoadAllAsset和LoadAssetWithSubAsset。这些api都有异步版本。同步api会比异步要快至少1帧。在5.1或者更老的版本可以这么说。因为在这些版本中一帧至多只加载一个Object。这意味着加载多个Object的异步api版本会比相应的同步版本慢很多。5.2之后修复了这个问题。可以再一帧里面加载多个Object,加载多少要视设置的时间片。

当要加载多个不相关的Object时应该用LoadAllAssets。但是也只有在加载大部分或者全部时才使用。相比另外两个API,LoadALL版本会稍微快一些。但是如果AssetBundle里面资源很多,而要加载的不超过三分之二。建议重新分割AssetBundle为多个更小的AssetBundle,然后调用LoadAll版本。

加载细节:

加载不是在主线程上面运行的。其中数据读取是在工作线程上执行的。5.3之前加载对象是顺序执行,而且某些部分职能在主线程上面执行。当工作线程读完数据。他就会暂停执行让主线程进行整合集成(integration),直到主线程整合完毕才继续工作。5.3之后,对象加载可以并行。多个对象可以再工作线程上面反序列化,处理和整合。当对象完成加载。Awake回调会执行,然后在下一帧就可用了。

3.5.2 AssetBundle依赖

Unity5 的AssetBundle系统。AssetBundle的依赖关系是可以通过两个不同的api自动跟踪的。在编辑器里面,依赖关系可以通过assetdatabase api来查询。AssetBundle的分配和依赖可以通过AssetImporter API来访问和改变。运行时可以通过ScriptableObject的子类的 AssetBundleManifest API来访问。

如果一个AssetBundle的object引用到一个或者多个另外一个AssetBundle的Object,我们就称为AssetBundle依赖。就像第一部分描述的,AssetBundle可以作为其内部包含的object的本地ID和GUID的数据源。

因为Object只有在实例ID首次被引用时才加载。而且AssetBundle被加载的时候,才会被赋予一个正确的实例ID。因此AssetBundle加载的顺序是无关的。重要的是要先于加载一个对象之前先加载它所依赖的AssetBundle们。Unity不会自动加载所有的依赖AssetBundle,这是开发者的责任。

比如一个材质A引用一个贴图B。A打包进AssetBundle1,B打包进AssetBundle2.在这个用例中,AssetBundle2必须先与从AssetBundle1中加载材质A之前加载。但这并不要AssetBundle2比AssetBundle1先加载。

Unity不会再AssetBundle1加载的时候自动加载AssetBundle2.这必须手工通过脚本加载。而且加载AssetBundle1和2的api是无关的。无论是通过哪种api加载都可以。

3.5.3 AssetBundle清单

当通过buildpipeline生成AssetBundle时候,unity会生成一个依赖关系信息到一个单独的AssetBundle里面。放在所有的AssetBundles存放的共同父目录里面。他的里面存放了一个 AssetBundleManifest类型。它提供了一个GetAllAseetBundles API来查询所有的AssetBundle。 GetAllDependencies返回所有的依赖。包括一个依赖的依赖,以及依赖的依赖的依赖等等。GetDirectDependencies只返回直接依赖。、

3.5.4 建议

建议只加载所需要的对象。特别是移动平台上,因为他们本地存储读取速度非常慢,而且加载和卸载Object会触发垃圾回收。

时间: 2024-10-18 21:14:25

Unity AssetBundles and Resources指引 (三) AssetBundle基础的相关文章

Unity AssetBundles and Resources指引 (一)

本文内容主要翻译自下面这篇文章 https://unity3d.com/cn/learn/tutorials/topics/best-practices/guide-assetbundles-and-resources?playlist=30089  A guide to AssetBundles and Resources 为了消除一些歧义,文章里面的专有名词直接用英文单词,比如Assets.Resource.Object 这篇文章是关于在unity引擎中进行Assets和resource管理

微信公众平台开发教程(三) 基础框架搭建

微信公众平台开发教程(三) 基础框架搭建 上一章,我们已经初步讲解了微信公众账号开发的基本原理,今天我们来探索设计实现. 首先我们设计了模块层次图,当然图中只是给出一种实现方式,不局限于此.具体见下图. 主要功能介绍如下: 1)请求接口层.处理HTTP请求,及响应 2)分发层.由接口层传入请求,然后具体分析请求类型,分发至不同的处理器 3)业务逻辑层.这里是我们的具体业务逻辑了,根据请求,实现具体的业务逻辑. 4)数据层.我们在实现某个应用时可能需要访问数据,可以是数据库或者是文件.如果是简单应

【Unity 3D】学习笔记三十四:游戏元素——常用编辑器组件

常用编辑器组件 unity的特色之一就是编辑器可视化,很多常用的功能都可以在编辑器中完成.常用的编辑器可分为两种:原有组件和拓展组件.原有组件是编辑器原生的一些功能,拓展组件是编辑器智商通过脚本拓展的新功能. 摄像机 摄像机是unity最为核心组件之一,游戏界面中显示的一切内容都得需要摄像机来照射才能显示.摄像机组件的参数如下: clear flags:背景显示内容,默认的是skybox.前提是必须在render settings 中设置天空盒子材质. background:背景显示颜色,如果没

(三)XML基础(3)

五.XPath:快速定位到节点 5.1 简介 5.2 语法 5.3 案例 XPath对有命名空间的xml文件和没有命名空间的xml定位节点的方法是不一样的,所以再对不同的xml需要进行不同的处理. 使用前提:  导入 Test_Xpath.java package dom; import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Doc

【Unity 3D】学习笔记三十七:物理引擎——碰撞与休眠

碰撞与休眠 上一篇笔记说过,当给予游戏对象刚体这个组件以后,那么这个组件将存在碰撞的可能性.一旦刚体开始运动,那么系统方法便会监视刚体的碰撞状态.一般刚体的碰撞分为三种:进入碰撞,碰撞中,和碰撞结束.关于休眠可以理解成为让游戏对象变成静止状态.如果给某个游戏对象休眠的状态,那么这个物体将立马静止,不再运动. 碰撞 首先学习下碰撞几个重要的方法: OnCollisionEnter(  ):刚体开始接触的时候,立即调用. OnCollisionStay(  ):碰撞过程中,每帧都会调用此方法,直到撞

【Unity 3D】学习笔记三十三:游戏元素——天空盒子

天空盒子 一般的3D游戏都会有着北京百年一遇的蓝天,让人惊叹不已.其实天空这个效果没有什么神秘的只需用到天空盒子这个组件就行,可以将天空设想成一个巨大的盒子,这个盒子将整个游戏视图和所有的游戏元素包含其中.在unity中制作天空盒子非常方便,只需要像设置其他组件一样设置下就行了.在制作天空盒子之前,我们需要搜集一些天空的贴图,不过,unity很方便的为开发者提供了天空盒子的资源包.首先在project视图中点击鼠标右键,然后选择import package--skyboxes即可添加天空盒子的资

Swift语言指南(三)--语言基础之整数和浮点数

整数 整数指没有小数的整数,如42,-23.整数可以是有符号的(正数,零,负数),也可以是无符号的(正数,零). Swift提供了8,16,32,64位形式的有符号和无符号的整数,这些整数遵循与C语言相似的命名规则.如8位无符号整数的类型为UInt8,32位有符号整数的类型为Int32,和Swift语言的其它类型一样,这些整型命名以大写字母开头. 整数的边界 你可以通过min或max属性为每一个整数类型指定一个最小值或最大值: 1 let 最小值 = UInt8.min // 最小值 等于 0,

3-JavaScript的三种基础弹框

JavaScript中三种基础弹框: 一.基础弹框 语法:alert() 举例: alert("123"); 二.确认框 语法:confirm(); 举例:var b = confirm("aa"); alert(b); 三.警告框 语法:prompt(text,value) 举例:var a = prompt("请输入你的用户名","boss"); alert(a);

【Unity 3D】学习笔记三十二:游戏元素——游戏光源

游戏光源 在3D游戏中,光源是一个非常具有特色的游戏组件.用来提升游戏画面质感的.如果没有加入光源,游戏场景可能就会显得很昏暗.在unity中提供了三种不同的光源类型:点光源,聚光灯,平行光. 点光源 顾名思义,点光源是从一个点向周围散发出光的光源,就像电灯一样.创建点光源在hierarchy视图中点击create--point light: 创建完以后,点击点光源对象,在右侧inspector视图中可以看到点光源的所有信息: type:光源的类型.有point(点光源),directional