• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

游戏开发

常州手游开发培训-Unity3d资源管理分析

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/youxikaifa/2019/0308/407.html

常州手游开发培训-Unity3d资源管理剖析

 



1.Unity3D占用内存太大的处理办法 

 

讨论AssetBundle-Resources-GameObject 的生命周期问题。对AssetBundle.Unload,Instantiate,Destory,UnloadUnusedAsset有细致的辨析。

 

根本信息

美术资源应导出为AssetBundle文件。这种AssetBundle有两种存储方式:能够是未紧缩的,也能够运用7z算法紧缩,默许紧缩。以我手头的一个蒙皮动画角色为例,紧缩后文件大小由800K减少到260K。导出过程中各个成分占的文件比例会在Logs中打印出来,以供剖析和优化。
AssetBundle有下面两个主要的加载办法:

  • AssetBundle.CreateFromFile只能加载未紧缩的文件。依据常州游戏开发培训文档的说法,该办法是最快的加载办法,但是不晓得这个"fast"是指“performace”还是"easy"。假如该算法是流式加载,可能的确是最快的,由于其他加载办法都有中间产物,例如CreateFromMemory或者WWW需会产生额外的byte[]。
  • AssetBundle.CreateFromMemory异步加载内存中二进制字节。这带来的益处是,硬盘上的文件能够运用自定义的方式组织、紧缩和打包。


性能和内存泄露

加载过程中会产生三级中间产物:

 

  1. AssetBundle
  2. Asset-Object:一切AssetBundle.Load*创立的Object,包括mainAsset
  3. Cloned-Object:Instantiate一个Asset-Object之后产生的Object

其中,AssetBundle是资源的静态二进制存档方式。此时资源并没有真正读出,只要执行Load操作资源才会被创立到Resouces系统中。Resources系统管理Asset-Object亦即实践的资源,包括贴图、mesh、Asset-GameObject。其中的Asset-GameObject十分相似Cloned-GameObject,但是无法挂载到场景中,无法被Destroy销毁,只能用Instantiate生成Cloned-Object。实践我们手机App外包看见的是Cloned-Object。

 

1. AssetBundle需求手工管理

 

 

Unity3d并没有追踪每个资源的来源。假设你重复加载同一个资源文件,每次AssetBundle.CreateFromFile/Memory都会创立一个新的AssetBundle,包含新的贴图、新的模型。为了减少这类误用,Unity在每个资源包的二进制内容中添加了一个随机包标志(包标志是导出时添加的,即便是同一个资源,每次导出都是不同的包)。Unity3d经过比拟包标志的方式,制止同时存在两个读取了相同资源包。若一个资源包对应的AssetBundle没有Unload,再次创立新的该资源的AssetBundle时会抛出错误:

 

  • The asset bundle '' can't be loaded because another asset with the same files are already loaded

 

但是Unity只是简单在AssetBundle创立时做了检查,在Asset-Object级没有记载包标志来源,也不会兼并相同资源。

  • 有一种不良做法:每次都重新读取资源包之后立刻释放包,将Instantiate出来的角色放在场景上。这种做法很简约不会惹起内存走漏,但是关于mmo rpg而言,场景上经常会有很多相同角色。每次App开发培训重新读取的资源包都会产生独立的Asset-Object,结果就是场景上的20只史莱姆会具有20份骨骼、20份贴图、20份材质、占用20份显存。

总的来说,项目框架需求手工管理AssetBundle,保证同一套资源不反复加载。

2. Asset-Object和Cloned-Object管理

一切AssetBundle.Load*加载的UnityEngine.Object,我们称为Asset-Object,与Instantiate发明出的 Cloned-Object相对应。

这两个概念在[1]的第一张配图中分别标志为”Asset-*“和”*-复制“。对成员mainAsset的访问实践上是完好的加载函数调用,为手工调用Load的简化版。另外经测试,重复Load同一个资源至少没有额外资源泄露。

在Unity自带的Profile系统中,Memory栏下 Textures/Meshes/Materials/AnimationClips/AudioClips指的就是Asset-Object。例如,从一个史莱姆Instantiate出很多史莱姆并不会增加Textures或者Meshes计数。

固然常州网站开发培训都是UnityEngine.Object,但是Asset-Object和Cloned-Object实质是不同的。例如,假如对Asset-Object执行Destroy,系统会报错:

 

  • Destroying assets is not permitted to avoid data loss.

 

Asset-Object是由Resources系统管理的,包括Asset中的Texture、AnimationClips等,为内存开支的主要来源。Resources系统运用弱援用管理Asset-Object,同时提供了Resources.UnloadUnusedAsset()以删除没有不再被强援用的Asset-Object。留意他检查的是一切强援用,并不限于场景中实践GameObject,所以假如你的代码中记载了的Asset表,还有某些代码的不测援用都会阻止这些资源被Resources系统释放。

 

  • 有一种错误了解:我们常州企业培训只需求AssetBundle.Unload(false),然后在删除场景内容时Object.Destroy(),这样能否就没有走漏了?答案能否定的,前者删除了AssetBundle,后者删除了Cloned-Object,但是Asset-Object还没有删除。Asset-Object由Resources系统管理,需求手工调用Resources.UnloadUnusedAsset()或者其他相似接口才干删除。

3. 场景管理

 

导出场景只能用BuildStreamedSceneAssetBundle,不能运用BuildAssetBundle。场景文件依然能够用CreateFromMemory读取,只不过Clone的时分必需运用Application.LoadLevel。而且LoadLevel过程和结果貌似不可控,比方你从程序上并不能得到“场景加载终了”或者“场景的内容是什么”这样的信息。

上篇:上一篇:常州手游开发-U3D AssetBundle爬坑
下篇:下一篇:U3D 客户端框架:资源管理器