关于Unity资源加载的细节
来源:互联网 发布:js给div添加点击事件 编辑:程序博客网 时间:2024/04/28 17:19
参考文章:http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html
Unity3D 里有两种动态加载机制:一个是Resources.Load,另外一个通过AssetBundle,其实两者区别不大。
Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时 动态加载,可以指定路径和来源的。
其实场景里所有静态的对象也有这么一个加载过程,只是Unity3D后台替你自动完成了。
详细说一下细节概念:
一、AssetBundle运行时加载:
1、 LoadFromFile:从指定本地磁盘路径加载,(注意这种方法只能用于standalone程序)这是最快的加载方法,(CreateFromFile方法在5.3.7版本被移除)
1.1、LoadFromFileAsync: 异步文件加载,从返回的AssetBundleCreateRequest对象的assetBundle字段中得到
2、 LoadFromMemory(byte[]): 从内存中加载,这个byte[]可以来自文件读取的缓冲,www的下载或者其他可能的方式。( CreateFromMemory方法在5.3.7版本被移除)
2.1、LoadFromMemoryAsync:异步内存加载,返回与LoadFromFileAsync相同。
其实WWW的assetBundle就是内部数据读取完后自动创建了一个assetBundle而已
Create完以后,等于把硬盘或者网络的一个文件读到内存一个区域,这时候只是个AssetBundle内存镜像数据块,还没有Assets的概念。
二、Assets的加载:
1、 AssetBundle.LoadAsset(string name):从AssetBundle的内存镜像里读取并创建一个Asset对象,创建Asset对象同时也会分配相应内存用于存放(反序列化) (AssetBundle.Load的重命名方法)
1.1、LoadAssetAsync(string name):异步加载,从返回的AssetBundleRequest对象的asset字段中得到
AssetBundle
2、LoadAssetWithSubAssets(string name):加载Asset及SubAssets,返回Object[] 或 T[] (5.0版本加入方法)
2.1、LoadAssetWithSubAssetsAsync(string name):异步加载Asset及SubAssets,返回AssetBundleRequest对象,从allAssets字段获取。
3、LoadAllAssets:加载全部Asset,可以指定Type,返回Object[] 或 T[] (AssetBundle.LoadAll的重命名方法)
3.1、 LoadAllAssetsAsync: 异步加载全部Asset,返回AssetBundleRequest对象,从allAssets字段获取。(5.0版本加入方法)
1、AssetBundle.Unload(flase)是释放AssetBundle文件的内存镜像,不包含Load创建的Asset内存对象。
2、AssetBundle.Unload(true)是释放那个AssetBundle文件内存镜像和并销毁所有用Load创建的Asset内存对象。
3、Resources.UnloadUnusedAssets: 释放所有没有被引用的Asset对象。
4、Resources.UnloadAsset(Object asset) :只会释放从本地加载的Asset对象。
四、Asset的Clone和使用:
当使用load好的Assets对象,要对其Clone一份并挂接到目标节点上,这是一个浅拷贝的过程,比如GameObject transform是新生成的,而像 mesh texture material shader只是引用了源Assets对象。
专门要提一下的是一个特殊的东西:Script Asset,看起来很奇怪,Unity里每个Script都是一个封闭的Class定义而已,并没有写调用代码,光Class的定义脚本是不会工作的。其 实Unity引擎就是那个调用代码,Clone一个script asset等于new一个class实例,实例才会完成工作。把他挂到Unity主线程的调用链里去,Class实例里的OnUpdate OnStart等才会被执行。多个物体挂同一个脚本,其实就是在多个物体上挂了那个脚本类的多个实例而已,这样就好理解了。在new class这个过程中,数据区是复制的,代码区是共享的,算是一种特殊的复制+引用关系。
当你Destroy一个实例时,只是释放那些Clone对象,并不会释放引用对象和Clone的数据源对象,Destroy并不知道是否还有别的object在引用那些对象。
等到没有任何 游戏场景物体在用这些Assets以后,这些assets就成了没有引用的游离数据块了,是UnusedAssets了,这时候就可以通过 Resources.UnloadUnusedAssets来释放,Destroy不能完成这个任 务,AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,因为它不管Asset是否被引用,都会释放,所以不安全。
配个图加深理解:(图是老图,理解就行)
五、注意
1、AssetBundle文件的内存镜像,并不是在托管堆上,所以GC是不会代你自动释放,每次使用完,记得调用Unload手动释放。
2、如果不再使用某个Asset,请确保没有变量指向这个Asset对象,或者Clone出来的对象,哪怕这个Clone出来的对象已释放,UnloadUnusedAssets也不能释放这个Asset,除非这个变量本来被销毁或者设为null。
3、在面向移动设备游戏的制作时,尽量减少在Hierarchy对资源的直接引用,而是使用Resource.Load的方 法,在需要的时候从硬盘中读取资源,在使用后用Resource.UnloadAsset()和Resources.UnloadUnusedAssets()尽快将其卸载掉。降低内存占用
4、如果DontDestroyOnLoad了一个包含很多资源(比如大量贴图或者声音等大内存占用的东西)的话,这部分资源在场景切换时无法卸 载,将一直占用内存
5、DontDestroyOnLoad的脚本,而这些脚本很可能含有对其他物体的Component或者资源的引用,这样相关的 资源就都得不到释放。
6、static的单例(singleton)在场景切换时也不会被摧毁,同样地,如果这种单例含有大量的对资源的引用,也会成为大问题
- 关于Unity资源加载的细节
- 关于Unity资源异步加载的研究
- Unity 关于资源加载的时间消耗
- 关于Unity资源的动态加载与WWW的使用
- Unity的动态加载AssetBundle资源笔记。
- Unity中加载资源的方法
- Unity资源加载的一些问题
- unity中资源动态加载的方式
- Unity加载资源的3种方法
- Unity 加载数据库资源
- Unity资源加载
- unity资源加载
- 关于懒加载的一些小细节
- Unity关于层级细节(LOD)的使用
- Unity关于层级细节(LOD)的使用
- Unity关于层级细节(LOD)的使用
- Unity中关于Grid的动态加载
- Unity 资源加载释放相关
- HDU 4549 M斐波那契数列(费马小定理,矩阵快速幂,快速幂)
- 淘宝JAVA中间件Diamond详解(1)-简介&快速使用
- Android Studio1.4.x JNI开发基础-基本环境配置
- wmi 局域网的相关问题以及解决方案
- 用 CSS 写一个向右的箭头
- 关于Unity资源加载的细节
- CentOS上的FirewallD简明指南
- 文章标题 Wireless Network
- 十进制二进制转换,C语言实现
- HTTP协议(言简意赅,总结到位)
- Eclipse安装教程 ——史上最详细安装java & python教程说明
- linux系统下运行NS2的脚本文件(.tcl文件)
- js清除浏览器缓存的几种方法(项目总结)
- Uri权限问题&&FileProvider学习