这篇文章包含哪些内容

这篇文章从Unity的Profile组件入手,来探讨一下Unity在开发环境和正式环境中的内存使用发面的一些区别,

并且给出了最好控制内存的方法(我想你已经知道了...Prefab ) ,以及原因。

 

提前需要阅读的文章

在阅读本文之前或之后我建议阅读一下以下几篇文章

 

雨松的

Unity3D研究院之Assetbundle的实战 http://www.xuanyusong.com/archives/2405/

Unity3D研究院之Assetbundle的原理 http://www.xuanyusong.com/archives/2373

 

王巍的

Unity 3D中的内存管理 http://onevcat.com/2012/11/memory-in-unity3d/

 

星尘(不太确定是否是原作者 哈)的

Unity3D占用内存太大的解决方法 http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html

 


从NGUI的AltasPacker说起

事情的起因还是因为我在学习使用NGUI(刚接触Unity没几天…), 教程看了看都没问题 自己动手操作的时候突然发现...

NGUI 创建UI时候必须都先要创建Altas,那我创建好后的散图是放在工程里面呢 还是要删掉? 不删会影响性能么? 

Google了一番并没有发现满意答案,所以只好自己Profile一下,于是有了如下实验:

 

1· 首先建立一个空场景,运行,打开Profile. Texture(纹理)部分使用内存2.5MB

 

2·加入一张图片,场景上不做任何引用。 该图片显存展开后大小为1.5MB , 运行 然后再打开Profile

 

3· 奇迹的事情发生了... 纹理占用的内存大小直接变为 5.8MB 

 

5.8MB- 2.5MB = 3.3MB 很奇怪的一个数,于是我同时怀疑三件事

 

1· 即使素材完全用不到但是如果工程中有导入则最后会被打包

2· 即使素材没有被当前场景使用,Unity仍旧会加载 ( Unity启动时候加载所有的素材??! )

3· Unity对素材在内存中有留有一份引用,3.3MB ~= 1.5MBx2 ( ??! ) 

 

如果以上三点有一个是真的(全是错的), 那Unity无疑直接变为废柴.... 

于是乎就此三点我开始无限的刨根问底.... 

功夫不负有心人吧,终于在一片帖子上面找到了突破口

http://answers.unity3d.com/questions/57909/find-unused-assets-in-project.html

这篇文章说的很清楚,Unity在发布时候会自动过滤掉未引用的所有资源,并且整个被打包进来的资源可以通过Log查看

根据文章指出的位置找到Log,并且就上面的工程进行测试,打出Android包  (Mac下Log在 /Users/eran/Library/Logs/Unity/Editor.log , eran为你的用户名)

 

这样的话 第一个心结就解开了, 看来Unity果真没有这么傻... 以后使用NGUI制作Atlas时候也不用担心是否需要删除小图这件事了.

既然知道了只有在真机设备上才可以进行测试,于是需要再将刚才做的测试重来一次了,只不过这次是在真机上面.

 

1· 首先建立一个空场景,运行,打开Profile. Texture(纹理)部分使用内存153.0KB

 

可以注意到,在真机上面运行时候 内存占用明显降低了,并且开销的线很平,不再像编辑环境一样会有波动.

 

2·加入一张图片并放置在场景上面

虽然没有像想象中的那样为1.5MB,不过 既然小于3MB,则Unity3D肯定不可能留有一份内存的备份(DRAM一份 VRAM一份,DRAM的用于处理LostConext时候重新上传GPU). 

这里面其实还有一个小插曲:

在Android上面 Rendering中显示 使用的显存为0,这点和我理解的3D渲染原理不符呀,一直让我困惑了很久。后来突然想到 难道是因为手机是共享显存的原因?

果不其然 当我把项目发布为PC版本时候 再跑Profile,显存占用就有数字了. 并且显存占用数和我后面说道的动态剔除还有关系,说明显存还发生了swap,这块和所讲的事情无关 就不细说了,如果大神对这块很了解 希望指点我一下.

 

ok 继续说上面提到一嘴的 动态剔除,这个是我无意发现的,

我把上面那张图加了一个Animation 让其左右移动,当我真机测试时候,当这张图片移出屏幕时候DrawCall会减1,也就是只要屏幕看不到的东西Unity会自动帮你剔除,

减少DrawCall, 其实细想想, 这个是很正常的一个事情,因为Unity是一个完全的3D引擎,这也是为什么在Unity里面没有像素 进来单位是Unit,没有屏幕的宽高,只能调整摄像机的视野. 

相比之下之前用的Starling,Cocos,虽然底层也在使用GPU进行渲染,但是他的整体引擎架构是基于2D的,所以自然无法在底层完成这种自动剔除以及显存交换的行为.相比之下Unity要优越许多.

就此Unity的一大谜题得以解开,根据上面的实验我得到了如下两条结论

 

结论: 即使项目中有许多未使用的图片,只要未放置在特殊文件夹下(Resource,StreamingAssets)并且没有被Prefab引用,最终导出时候不会被打包,更不会占用显存,但是在开发阶段会.

 

结论: Unity 会自行对移出场景的对象进行剔除从而减少DrawCall

 


Prefab 最好的管理内存(显存)的方式

我的刨根问底行为到这里并没有结束, 既然知道了Unity如何加载素材,那他什么时候卸载呢?

我又做了如下实验:

 

建立两个场景,SceneA,SceneB. 在SceneA中加载一张纹理,同时提供一个跳转到SceneB的按钮. 

点击按钮跳转到SceneB,SceneB是一个空场景 什么都不放. 

预期的是当切换到SceneB时候SceneA中所占用的显存应该会被释放,不过结果却又是让人大失所望... 仍旧没有变化

即使我在SceneB中调用GC都没用(其实看过GC介绍的朋友也应该知道在那里调GC本来就应该没用)

 

最后又是一通Google,不过这次没有像上次那么走运 没有任何的收获,这也是我后来转向开始研究Prefab的原因. 不过还是继续把这里说完. 

又是一次意外的测试,我发现当我再建立一个SceneC时候, 由SceneA->SceneB->SceneC 这个时候 SceneA中的显存会得到释放. 就此问题我还发了一个Question. 

有个朋友给了他项目上的证实,Unity确实如此 http://ask.unitymanual.com/question/36097

 

既然Unity自动管理的内存需要跨两个场景才能消除,那我们有没有办法自己控制呢? 方法是有的 那就是使用Prefab.

如何创建及如何使用Prefab 松雨的那两篇文章已经说的非常明白了,我就不重复造轮子了.

 

结论: Unity自身的显存回收是需要经过跨两个场景,如果使用Prefab在调用assetBundle.Unload (true)时候可以释放显存。

 

以上是我这几天通过实验摸索的一些经验,希望能对你有所帮助。如果哪里说的不对还请大神指出

谢谢

 

posted @ 2015-03-24 15:42 zhepama 阅读(2145) 评论(0) 推荐(0) 编辑
摘要: U3D中的Profile也是可以直接在链接安卓设备运行游戏下查看的,导出真机链接U3D的Profile看数据,这样能更好的测试具体原因。大概看了下官方的做法,看了几张帖子顺带把做法记录下来。参考:http://docs.unity3d.com/Documentation/Manual/Profile... 阅读全文
posted @ 2015-03-24 15:19 zhepama 阅读(3229) 评论(0) 推荐(0) 编辑
摘要: 关于本文 本文主要讲解从数学的角度如何推导出Stage3D中用到的两个投影矩阵perspectiveLHpublic function perspectiveLH(width:Number,height:Number,zNear:Number,zFar:Number):void{ this.co... 阅读全文
posted @ 2015-03-24 12:24 zhepama 阅读(622) 评论(0) 推荐(0) 编辑
摘要: 关于本文本文并无打算事无巨细的介绍一遍AGAL,仅仅是对现有文档的一些理解及汇总,所以请先阅读相参考文档AGAL概念参考资料http://www.adobe.com/devnet/flashplayer/articles/what-is-agal.html(英文)http://www.adobe.c... 阅读全文
posted @ 2015-03-24 12:22 zhepama 阅读(570) 评论(0) 推荐(0) 编辑
摘要: 关于本文本文主要想介绍一下3D渲染的基本流程,及怎样把一个三角形(0,1,0),(1,0,1),(0,0,1)最终渲染到屏幕上来。文章的目的是对3D渲染流程做一个简单的介绍,其中不涉及任何语言的API参考资料《3D游戏编程大师技巧》 PFD地址http://download.csdn.net/det... 阅读全文
posted @ 2015-03-24 12:21 zhepama 阅读(1954) 评论(1) 推荐(0) 编辑
摘要: 对项目优化有很多,如:mesh合并 ,减少DrawCall和模型骨骼以及物理计算,合并材质球,优化代码等等,前面发过一篇【整理】unity3d优化总结篇现在继续补上,该内容为本人经验以及网上收集整理,希望大家有更好的优化方法,能够继续跟帖,一起探讨,共同进步。优化:1. 更新不透明贴图的压缩格式为E... 阅读全文
posted @ 2015-03-24 12:08 zhepama 阅读(1705) 评论(0) 推荐(0) 编辑
摘要: 一.在项目根目录中创建Resources文件夹来保存文件。可以使用Resources.Load("文件名字,注:不包括文件后缀名");把文件夹中的对象加载出来。注:此方可实现对文件实施“增删查改”等操作,但打包后不可以更改了。二.直接放在项目根路径下来保存文件在直接使用Application.dat... 阅读全文
posted @ 2015-03-24 11:43 zhepama 阅读(10353) 评论(0) 推荐(1) 编辑
摘要: Now then, let's get started.1.Open thePlayscene which you had created in the previous post. If you've not created thePlayscene, create a New Scene and... 阅读全文
posted @ 2015-03-23 22:20 zhepama 阅读(573) 评论(0) 推荐(0) 编辑
摘要: In thefirst sceneor maybe theMain Menu sceneof your game Create anEmpty Gameobject. Call it whatever you like, for reference, I would call it asGO_Loa... 阅读全文
posted @ 2015-03-23 22:19 zhepama 阅读(1065) 评论(0) 推荐(0) 编辑
摘要: 用Unity3D制作基于web的网络游戏,不可避免的会用到一个技术-资源动态加载。比如想加载一个大场景的资源,不应该在游戏的开始让用户长时间等待全部资源的加载完毕。应该优先加载用户附近的场景资源,在游戏的过程中,不影响操作的情况下,后台加载剩余的资源,直到所有加载完毕。本文包含一些代码片段讲述实现这... 阅读全文
posted @ 2015-03-23 20:24 zhepama 阅读(407) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示