关于Unity资源加载的细节
2017-06-30 14:24
411 查看
参考文章: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版本加入方法)
三、AssetBundle和Assets的释放:
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是否被引用,都会释放,所以不安全。
配个图加深理解:(图是老图,理解就行)
![](http://images.cnitblog.com/blog/90192/201303/15162026-0158e692a60c4c849d482be37465ff58.jpg)
五、注意
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)在场景切换时也不会被摧毁,同样地,如果这种单例含有大量的对资源的引用,也会成为大问题
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是否被引用,都会释放,所以不安全。
配个图加深理解:(图是老图,理解就行)
![](http://images.cnitblog.com/blog/90192/201303/15162026-0158e692a60c4c849d482be37465ff58.jpg)
五、注意
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 中使用AssetBundle加载资源,shader偶尔会丢失的问题解决办法
- 关于Unity资源异步加载的研究
- Unity 关于AssetBundle(资源束)打包和加载(一)
- Unity+NGUI中关于多分辨率对应多套资源的解决方案
- [unity基础教程]关于Unity3D中Resources动态加载NGUI图片的方法!
- unity基础开发----Unity3D的uniSWF插件动态加载SWF UI资源
- unity基础开发--实现动态加载资源
- Unity 3D--外部加载资源AssetBundles
- [unity基础教程]Unity3D实现动态加载游戏资源(转)
- 关于Laszlo(2.x 3.0)无法动态加载资源的问题
- unity动态加载远程资源
- 关于一个无法加载资源的错误问题
- unity动态加载远程资源
- 全面理解Unity加载和内存管理机制之二:进一步深入和细节
- 全面理解Unity加载和内存管理机制之二:进一步深入和细节
- 关于webview 加载本地图片资源 显示不出来的解决办法
- 关于DI容器UnityContainer的Dispose方法释放资源的一点理解
- Unity加载Web资源需求crossdomain.xml文件格式
- Unity动态加载远程资源