Unity载入和内存管理机制
Unity几种动态载入Prefab方式的差异:
事实上存在3种载入prefab的方式:
一是静态引用,建一个public的变量,在Inspector里把prefab拉上去,用的时候instantiate
二是Resource.Load,Load以后instantiate
三是AssetBundle.Load,Load以后instantiate
三种方式有细节差异。前两种方式,引用对象texture是在instantiate时载入,而assetBundle.Load会把perfab的所有assets都载入。instantiate时仅仅是生成Clone。所曾经两种方式,除非你提前载入相关引用对象。否则第一次instantiate时会包括载入引用类assets的操作,导致第一次载入的lag。官方论坛有人说Resources.Load和静态引用是会把所有资源都预先载入的。重复測试的结果,静态引用和Resources.Load也是OnDemand的。用到时才会载入。
几种AssetBundle创建方式的差异:
CreateFromFile:这样的方式不会把整个硬盘AssetBundle文件都载入到内存来,而是类似建立一个文件操作句柄和缓冲区,须要时才实时Load,所以这样的载入方式是最节省资源的。基本上AssetBundle本身不占什么内存。仅仅须要Asset对象的内存。可惜仅仅能在PC/Mac
Standalone程序中使用。
CreateFromMemory和WWW.assetBundle:这两种方式AssetBundle文件会整个镜像于内存中。理论上文件多大就须要多大的内存。之后Load时还要占用额外内存去生成Asset对象。
什么时候才是UnusedAssets?
看一个样例:
Object obj = Resources.Load("MyPrefab");
GameObject instance = Instantiate(obj) as GameObject;
.........
Destroy(instance);
创建随后销毁了一个Prefab实例,这时候 MyPrefab已经没有被实际的物体引用了。但假设这时:
Resources.UnloadUnusedAssets();
内存并没有被释放,原因:MyPrefab还被这个变量obj所引用
这时候:
obj = null;
Resources.UnloadUnusedAssets();
这样才干真正释放Assets对象
所以:UnusedAssets不但要没有被实际物体引用。也要没有被生命周期内的变量所引用。才干够理解为
Unused(引用计数为0)
所以所以:假设你用个全局变量保存你Load的Assets,又没有显式的设为null,那在这个变量失效前你不管怎样UnloadUnusedAssets也释放不了那些Assets的。假设你这些Assets又不是从磁盘载入的,那除了UnloadUnusedAssets或者载入新场景以外没有其它方式能够卸载之。
一个复杂的样例,代码非常丑陋实际也不可能这样做。仅仅是为了加深理解
IEnumerator OnClick()
{
Resources.UnloadUnusedAssets();//清干净以免影响測试效果
yield return new WaitForSeconds(3);
float wait = 0.5f;
//用www读取一个assetBundle,里面是一个Unity基本球体和带一张大贴图的材质。是一个Prefab
WWW aa = new WWW(@"file://SpherePrefab.unity3d");
yield return aa;
AssetBundle asset = aa.assetBundle;
yield return new WaitForSeconds(wait);//每步都等待0.5s以便于分析结果
Texture tt = asset.Load("BallTexture") as Texture;//载入贴图
yield return new WaitForSeconds(wait);
GameObject ba = asset.Load("SpherePrefab") as GameObject;//载入Prefab
yield return new WaitForSeconds(wait);
GameObject obj1 = Instantiate(ba) as GameObject;//生成实例
yield return new WaitForSeconds(wait);
Destroy(obj1);//销毁实例
yield return new WaitForSeconds(wait);
asset.Unload(false);//卸载Assetbundle
yield return new WaitForSeconds(wait);
Resources.UnloadUnusedAssets();//卸载无用资源
yield return new WaitForSeconds(wait);
ba = null;//将prefab引用置为空以后卸无用载资源
Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(wait);
tt = null;//将texture引用置为空以后卸载无用资源
Resources.UnloadUnusedAssets();
}
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbmV5c3R1ZHk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbmV5c3R1ZHk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
说明:
1 初始状态
2 加载AssetBundle文件后,内存多了文件镜像。用量上升,Total
Object和Assets添加1(AssetBundle也是object)
3 加载Texture后。内存继续上升,由于多了Texture
Asset,Total Objects和Assets添加1
4 载入Prefab后,内存无明显变化,由于最占内存的Texture已经载入,Materials上升是由于多了Prefab的材质,Total
Objects和Assets添加6,由于 Perfab 包括非常多 Components
5 实例化Prefab以后,显存的Texture Memory、GameObjectTotal、Objects
in Scene上升。都是由于实例化了一个可视的对象
6 销毁实例后,上一步的变化还原,非常好理解
7 卸载AssetBundle文件后,AssetBundle文件镜像占用的内存被释放。对应的Assets和Total
Objects Count也减1
8 直接Resources.UnloadUnusedAssets,没有不论什么变化。由于全部Assets引用并没有清空
9 把Prefab引用变量设为null以后。整个Prefab除了Texture外都没有不论什么引用了。所以被UnloadUnusedAssets销毁,Assets和Total
Objects Count减6
10 再把Texture的引用变量设为null,之后也被UnloadUnusedAssets销毁。内存被释放,assets和Total
Objects Count减1。基本还原到初始状态
从中也能够看出:
Texture载入以后是到内存,显示的时候才进入显存的Texture Memory。
全部的东西基础都是Object
Load的是Asset,Instantiate的是GameObject和Object in Scene
Load的Asset要Unload,new的或者Instantiate的object能够Destroy
Unity载入和内存管理机制的更多相关文章
- 演示unity内存管理机制的缺陷
概述 这是最近做项目时发现的一个内存管理机制上的一个缺陷,但是我并不知道这究竟是不是一个bug,因为他可以造成内存泄漏,但是却能避开野指针. 详细 代码下载:http://www.demodashi. ...
- php内存管理机制、垃圾回收机制
一.内存管理机制 先看一段代码: <?php //内存管理机制 var_dump(memory_get_usage());//获取内存方法,加上true返回实际内存,不加则返回表现内存 $a = ...
- 浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...
- ARC内存管理机制详解
ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...
- 深入了解C#系列:谈谈C#中垃圾回收与内存管理机制
今天抽空来讨论一下.Net的垃圾回收与内存管理机制,也算是完成上个<WCF分布式开发必备知识>系列后的一次休息吧.以前被别人面试的时候问过我GC工作原理的问题,我现在面试新人的时候偶尔也会 ...
- 【Cocos2d-x 3.x】内存管理机制与源码分析
侯捷先生说过这么一句话 : 源码之前,了无秘密. 要了解Cocos2d-x的内存管理机制,就得阅读源码. 接触Cocos2d-x时, Cocos2d-x的最新版本已经到了3.2的时代,在学习Coco ...
- Spark 1.6以后的内存管理机制
Spark 内部管理机制 Spark的内存管理自从1.6开始改变.老的内存管理实现自自staticMemoryManager类,然而现在它被称之为"legacy". " ...
- python的内存管理机制
先从较浅的层面来说,Python的内存管理机制可以从三个方面来讲 (1)垃圾回收 (2)引用计数 (3)内存池机制 一.垃圾回收: python不像C++,Java等语言一样,他们可以不用事先声明变量 ...
- Java虚拟机内存管理机制
自动内存管理机制 Java虚拟机(JVM)在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区 ...
随机推荐
- windows批处理命令学习
初入批处理的学习,发现运行window的系统命令会减少很多的劳动,很方便. 参考例子: http://www.jb51.net/article/41322.htm
- CANO入门(三)
最好的学习方式是什么?模仿.有人会问,那不是山寨么?但是我认为,那是模仿的初级阶段,当把别人最好的设计已经融化到自己的血液里,变成自己的东西,而灵活运用的时候,才是真正高级阶段.正所谓画虎画皮难画骨. ...
- 【TEST】NOI-Linux可用 gedit c++精简配置 附Emacs日常配置
这里是backup的测试随笔,用于测试 CSS / Markdown 效果. 同时也是是本菜鸡考场上一般使用的Gedit配置. 只有6行,挺短的.应该算好记吧. 使用之前记得勾选首选项里的外部工具. ...
- [ CodeVS冲杯之路 ] P1220
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1220/ 一个标准的DAG上的DP,设 f[i][j] 为在第 i 行第 j 最大分数 因为这个状态是无后效性的,所以可 ...
- redis 的命令总结
此博客为技术收集和个人的学习积累,如侵犯了您的权益,请联系我,我会及时删除,谢谢 [Redis] redis-cli 命令总结 Redis提供了丰富的命令(command)对数据库和各种数据类型进行操 ...
- c中结构体的4种定义
1.常规的标准方式: 1 #include <stdio.h> 2 3 struct student{ 4 int age; 5 float score; 6 ...
- (七)ubuntu下编译openwrt内核的环境配置
首先安装基本开发环境: sudo apt-get install ssh vim samba tftp nfs 安装编译openwrt须要的包: 解压openwrt包编译出错: Build depen ...
- pageHelper插件+传统分页处理
为什么要使用pageHelper:https://www.cnblogs.com/ljdblog/p/6725094.html 配置文件详解:https://www.cnblogs.com/cksvs ...
- ubuntu下安装 gSOAP 用于C/C++开发web service服务端与客户端
昨天在ubuntu下进行安装gSOAP,费了很多时间,没成功,今天又来找了大量教程资料,终于一次成功,这里写下自己的安装步骤和方法,供大家参考. 首先下载gsoap,我下载的是gsoap-2.8.1. ...
- ajax和json数据
一.Ajax概述 1.什么是同步,什么是异步 同步现象:客户端发送请求到服务器端,当服务器返回响应之前,客户端都处于等待 卡死状态 异步现象:客户端发送请求到服务器端,无论服务器是否返回响应, ...