Unity3D占用内存太大怎么办呢? -下
什么时候才是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();
-
}
这是测试结果的内存Profile曲线图
Unity3D占用内存太大怎么解决呢?
图片:p12.jpg
很经典的对称造型,用多少释放多少。
这是各阶段的内存和其他数据变化
Unity3D占用内存太大怎么解决呢?
图片:p13.jpg
说明:
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 3D中的内存管理
Unity3D在内存占用上一直被人诟病,特别是对于面向移动设备的游戏开发,动辄内存占用飙上一两百兆,导致内存资源耗尽,从而被系统强退造成极 差的体验。类似这种情况并不少见,但是绝大部分都是可以避免的。虽然理论上Unity的内存管理系统应当为开发者分忧解难,让大家投身到更有意义的事情中 去,但是对于Unity对内存的管理方式,官方文档中并没有太多的说明,基本需要依靠自己摸索。最近在接手的项目中存在严重的内存问题,在参照文档和 Unity Answer众多猜测和证实之后,稍微总结了下Unity中的内存的分配和管理的基本方式,在此共享。
虽然Unity标榜自己的内存使用全都是“Managed Memory”,但是事实上你必须正确地使用内存,以保证回收机制正确运行。如果没有做应当做的事情,那么场景和代码很有可能造成很多非必要内存的占用, 这也是很多Unity开发者抱怨内存占用太大的原因。接下来我会介绍Unity使用内存的种类,以及相应每个种类的优化和使用的技巧。遵循使用原则,可以 让非必要资源尽快得到释放,从而降低内存占用。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgffhbc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13