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 newWaitForSeconds(3);
float wait = 0.5f;
//用www读取一个assetBundle,里面是一个Unity基本球体和带一张大贴图的材质,是一个Prefab
WWW aa = newWWW(@"file://SpherePrefab.unity3d");
yield return aa;
AssetBundle asset =aa.assetBundle;
yield return newWaitForSeconds(wait);//每步都等待0.5s以便于分析结果
Texture tt = asset.Load("BallTexture")as  Texture;//加载贴图
yield return newWaitForSeconds(wait);
GameObject ba =asset.Load("SpherePrefab") as  GameObject;//加载Prefab
yield return newWaitForSeconds(wait);
GameObject obj1 = Instantiate(ba)as GameObject;//生成实例
yield return newWaitForSeconds(wait);
Destroy(obj1);//销毁实例
yield return newWaitForSeconds(wait);
asset.Unload(false);//卸载Assetbundle
yield return newWaitForSeconds(wait);
Resources.UnloadUnusedAssets();//卸载无用资源
yield return newWaitForSeconds(wait);
ba = null;//将prefab引用置为空以后卸无用载资源
Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(wait);
tt = null;//将texture引用置为空以后卸载无用资源
Resources.UnloadUnusedAssets();
}
这是测试结果的内存Profile曲线图

很经典的对称造型,用多少释放多少。这是各阶段的内存和其他数据变化

说明:
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加载和内存管理机制之二:进一步深入和细节相关推荐

  1. 全面理解Unity加载和内存管理

    转载自:http://www.ceeger.com/forum/read.php?tid=4394 最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Resourc ...

  2. Unity动态加载和内存管理(三合一)

    原址:http://game.ceeger.com/forum/read.php?tid=4394#info 最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Re ...

  3. Unity3D资源加载与内存管理

    Unity3D资源加载与内存管理 Unity 3D中的资源加载 AssetBundle运行时加载: Unity3D占用内存太大怎么解决呢? 关于内存管理 举两个例子帮助理解 额外问题 Hog的评论引用 ...

  4. 【深入理解Java虚拟机】自动内存管理机制——垃圾回收机制

      Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...

  5. Unity 全面理解加载和内存管理

    最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBundle,其实两者本质上我理解没有什么区别.Resources ...

  6. Python源码阅读-内存管理机制(二)

    arena arena: 多个pool聚合的结果 arena size pool的大小默认值位4KB arena的大小默认值256KB, 能放置 256/4=64 个pool obmalloc.c中代 ...

  7. Linux驱动学习--android中的内存管理机制ION(二)--ION的使用

    目录 一.引言 二.ION框架 ------> heap类型 ------> ion特性 三.ion的使用 ------> 基本数据结构 ------> 具体的使用 四.ion ...

  8. Unity加载机制及内存管理

    原文地址: http://game.ceeger.com/forum/read.php?tid=4394 作者写的非常精彩~ 一 Unity里有两种动态加载机制 1,Resources.Load:从一 ...

  9. 【OS学习笔记】十 实模式:实现一个程序加载器-程序加载器如何将用户程序加载到内存并执行

    上一篇文章学习了以下内容: 用一种不同的分段方法,从另一个不同的的角度理解处理器的分段内存访问机制 使用循环和条件转移指令来优化主引导扇区代码 点击链接查看上一篇文章:点击链接查看 对于主引导扇区部分 ...

最新文章

  1. JUC 常用 4 大并发工具类
  2. java学习笔记6--类的继承、Object类
  3. CCNA-Cisco-Packet-Tracerchs(思科官网)安装教程以及使用
  4. Swift调用Objective C的FrameWork
  5. VBoxManage获取虚拟机IP地址
  6. 小米8大幅降价促销 性价比十足!
  7. Excel文件处理实战-Python编程进阶
  8. AM3352启动分析:
  9. 微信小程序云开发视频教程上线啦
  10. 音视频处理入门基础知识
  11. VMware8序列号
  12. 浪潮服务器支持pcie ssd硬盘吗,PCI-E与SATA SSD如何选?一分钟看懂
  13. 在TX2上(arm架构)安装FastDB
  14. packet协议源码解析
  15. c# 获取本地主机的ip地址
  16. 留言赠书|GitHub收获1W星标《迁移学习导论》重新整理升级
  17. Android画图方式
  18. 雷军北大15分钟演讲:我至少有胆量去想
  19. 基于SSH开发校园失物招领网
  20. flutter 格式化时间

热门文章

  1. 定义空列表元素类型_【Python+Excel】做数据分析5--列表和元组读取和常用查询
  2. 计算机和学数制和码制,[文学]第二章 计算机中的数制和码制.ppt
  3. layui搭建的php后台,使用layui框架搭建后台布局
  4. php hook 键盘,Windows C++ 键盘钩子
  5. php urledcode_攻防世界 php 2 函数urldecode 使用说明
  6. log4j slf4j实现_日志那点事儿——slf4j源码剖析
  7. 解封装(四):avformat_find_stream_info探测获取封装上下文并打印
  8. python字符的大小比较_python中字符串怎么比较大小
  9. 利用函数重载编写函数max_c++笔记(函数重载)
  10. mysql ibdata1 损坏_mysql innodb文件ibdata1损坏导致mysql无法启动