Unity 内存管理

作者:终点 原文地址:http://gad.qq.com/article/detail/7192174

Unity 内存管理

为什么在unity项目开发中的内存占用是一个非常大的问题,那是因为一些场景和代码造成的非必要内存的占用,那么这种问题如何解决呢?下面会为大家unity中的内存管理,了解内存的种类以及对应种类的优化和使用的技巧。

三种内存

·                     程序代码

·                     托管堆(Managed Heap)

·                     本机堆(Native Heap)

程序代码就是Unity引擎本身以及我们使用的各种库,还有自己写的程序代码,这些代码段是要载入内存才能使用的

我们要尽量减少不必要的库被打包进最终的包里,具体可以看Optimizing the Size of the BuiltiOS Player

托管堆就是C#/Mono代码使用的内存。托管堆是有GC(Garbage Collect)机制的,这使得我们不需要手动delete任何实例
需要注意的是,这一块本质上一个被虚拟机管理的内存,在我们创建Class的实例时,如果虚拟机空间不足,是会申请新的空间的,但是,这个空间不会再被释放回去就是说,托管堆只会增长不会减少,即使你的C#类的实例都被GC掉了,但虚拟机还是要占那么多的内存的

在iOS中,为了提供64的支持,Unity开启了IL2CPP项目,但是这个东西也还是一个虚拟机,我们的C#代码虽然被翻译成了C++代码,但它的内存管理逻辑和C#还是一样的

托管堆还有一个坑是GCGC会造成线程停顿,主线程需要停下来来完成GC操作。所以,在战斗过程中,要尽量避免Managed Heap的请求和释放(主要是释放)

C#提供了值语义来实现简单的类C++RAII的概念,可以避免频繁的GC。但要注意box/unbox问题

本机堆可以是Unity自己管理的一部分内存,主要是一些Native的资源,比如贴图,音效,关卡数据等。这部分内存我们也可以自己申请和使用的,我们使用native插件也是使用这部分内存。

在C#代码中,我们也可以申请和使用Native Heap的:

1
2
int size = 65536; //1024;
       byte * buffer = ( byte *)Marshal.AllocHGlobal(size);

Marshal.aspx)是C#提供的一个直接操作Native内存的接口,通过这个系统,我们可以绕过GC系统,手动管理内存,以在某些情况下大幅优化C#的性能

在Unity中,有一套自动的资源加载和卸载的机制,这使我们不需要在代码中指定任何资源的加载过程,我们想要显示的时候,它就会在哪里了,非常方便。但是,这样我们也失去了手动管理资源的权力,很容易导致Unity吃掉大量的内存

UnityAsset使用了一套引用计数的系统来管理
Unity 内存管理
当我们使用Unity的Profiler来观察内存占用情况时,我们可以看到每个Asset后面会有一个Refcount的数字,而右边列出引用了它的东西,这些一般是具体的C#实例

如果一个Asset没有了引用,使用Resources.UnloadUnusedAssets()就可以卸载它了。使用Resource.UnloadAsset()可以强制卸载一个资源,但是如果它还有引用,它会被再次加载进来的

Unity默认会在切换Scene时自动卸载所有资源,因为所有的C#实例都被销毁掉了

我们要在一个Scene中动态的加载和卸载资源,就要用Resource.UnloadAsset()了。尽量不要使用Resources.UnloadUnusedAssets()因为它是一个遍历查找的操作,会造成卡顿

AssetBundle加载

AssetBundleUnity提供的唯一的资源更新方法,非常有用

它的整个操作周期可以使用下图来表示:

Unity 内存管理

Instantiate指的是PrefabGameObject.Instantiate这个函数会实例化一个Prefab,这个Prefab所使用的Asset会根据不同的类型,进行引用Clone或者Clone(复制)+引用的形式来产生

AssetBundle.Load就是一个反序列的过程,它会创建一个GameObject出来,这个GameObject可以用来实例化成我们真正可用,挂载在场景树中的GameObejct

AssetBundle压缩

注意上图的紫色的AssetBundleMemory部分

Unity 内存管理

一般来说,我们要使用LoadFromCacheOrDownload来加载AssetBundle因为这样可以避免这部分内存占用。但是,Unity其实是把AssetBundle解压到一个Cache里然后加载的,还是会增加本地的磁盘占用的,在iOS中,这个占用还是比较麻烦的。因为LZMA压缩可以节省80%左右的磁盘占用,这意味着,解压后会放大五六倍

在Unity5.3中,引入了一个新的压缩方式LZ4,它是一个chunk-based(基于块)的压缩方式,它的好处就是,在读区时我们可以只解压指定的chunks而不必如LZMA一样,解压整个AssetBundle文件到内存

LZ4可以节省40%–60%的空间,同时实时读取解压时的性能消耗还可以接受

Unity 内存管理

可以看到,LZ4版本的AssetBundle中加载prefab性能下降还是很明显的

需要注意的是,在5.3后的版本中,WWW.LoadFromCacheOrDownload默认产生的Cache,都是使用LZ4压缩的,而不是完全解压后的版本。如果你注意到AssetBundle中加载资源比Resources中慢,检查一下这个

使用LZ4可以解决iOS中,游戏占用过多磁盘空间的问题,同时带来的性能消耗还可以接受。
使用LZ4我们就可以直接使用LoadFromFile来加载AssetBundle了,而且不必调用AssetBundle.Unload(false)来释放内存空间,也不必卸载AssetBundle本身了。AssetBundle甚至可以被看作一个简单的虚拟文件系统了,只要挂上就可以了

引用:

·                     Unity Internals: Memory andPerformance

·                     Asset Bundle Compression


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值