【Unity】运行时刻资源管理

Unity运行时刻资源管理html

 

----------------------------------------------------------------------------------------算法

Asset Bundles    网络

制做:BuildPipeline.BuildAssetBundle()    框架

加载:AssetBundle.Load()    koa

卸载:AssetBundle.Unload(bool unloadAllLoadedObjects)        异步

unloadAllLoadedObjects = true:释放解压数据,全部已实例化的资源亦被释放。        ide

unloadAllLoadedObjects = false:释放解压数据,已实例化的资源不释放。函数

Resource Folders    post

制做:Project视图中任意名为“Resources”文件夹下的资源,不管场景中是否用到。    性能

加载:Resources.Load()   

  卸载:Resources.UnloadUnusedAssets(),实例经过Object.Destroy()释放。    

工做方式:         全部Resources资源及其相关资源都存储于resources.assets中,但若是有资源被某场景使用,该资源则被存储于该场景对应的sharedassets<0~n>.assets中。         若是编译目标平台为Streaming Web Player,则状况略有不一样。你能够在设置中经过First Streamed Level With Resources一项指定全部Resources资源跟随哪一场景(Level)加载。在该模式下,全部先于“First streamed Level”加载的场景,用到的Resource资源同上,都存储于其对应的sharedassets中;后于“First streamed Level”加载的场景,其用到的Resource资源,却存储于resources.assets中。

----------------------------------------------------------------------------------------
Streaming  Web Players    

该模式中的Streaming是以场景(Level)为单位的,你能够在编译设置中指定各个场景的载入顺序,Unity Web  Player会按该顺序自发异步加载各场景。同时,Unity也提供了经过WWW加载.unity3d场景文件的API,使开发者对场景加载有更灵活的控制权。       实际上,WWW能够用于网络下载任意资源(纹理、文本、二进制文件),视频和音频也能够经过WWW下载,并且能够作到边下载边播放。
AssetBundle

----------------------------------------------------------------------------------------

想打包进AssetBundle中的二进制文件,其文件名后缀必须为“.bytes”,Unity会将其视为TextAssets对待。
AssetBundle  bundle =  www.assetBundle;

获取WWW.assetBundle的一刻,由WWW下载的数据压缩包被解压,AssetBundle对象被建立,此时你能够用AssetBundle.Load()实例化资源了。
除非使用AssetBundle.LoadAll()获取全部资源,不然没法获得一个AssetBundle中的资源列表。通常作法是在该AssetBundle中放置一个定好名称的TextAsset,在其中维护一份全部资源的名称列表。
一个AssetBundle包能够引用其余AssetBundle包中的资源。制做时,须要调用BuildPipeline.PushAssetDependencies()和BuildPipeline.PopAssetDependencies()函数对;加载时,被引用的包须要先于引用包加载。 另外,重编这种包须要开启BuildAssetBundleOptions.DeterministicAssetBundle,以保证每次重编时所使用的资源ID都是同样的。
你能够在一个游戏里使用另外一个游戏的AssetBundle,前提是该AssetBundle中所引用的资源,要么存在于该AssetBundle中,要么已经被载入了游戏中。为确保AssetBundle引用的资源被编进同包中,制做时可使用BuildAssetBundleOptions.CollectDependencies选项。

----------------------------------------------------------------------------------------
AssetDatabase Unity  Editor使用AssetDatabase维护项目中的全部资源文件,Unity使用这套API取代传统的filesystem。这是一个Editor类,因此只有在名为“Editor”的文件夹下的Script中才有用。

BuildPipeline.BuildStreamedSceneAssetBundle()或BuildPipeline.BuildPlayer(...,  BuildOptions.BuildAdditionalStreamedScenes)生成的场景包,使用WWW下载后,只需调用WWW.assetBundle,而不需AssetBundle.LoadAll(),便可激活包中的场景,即调用WWW.assetBundle后,你就能够经过Application.LoadLevel()来载入场景了。

 

 

http://blog.csdn.net/ox_thedarkness/article/details/9197453

分离资源管理

参考

1.Unity3D占用内存太大的解决方法 - 星尘

 

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

 

http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html

 

讨论基于Unity3d 4.1.5,不定时更新。

基本信息

美术资源应导出为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。实际咱们看见的是Cloned-Object。

 

1. AssetBundle须要手工管理

 

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

 

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

 

可是Unity只是简单在AssetBundle建立时作了检查,在Asset-Object级没有记录包标志来源,也不会合并相同资源。

  • 有一种不良作法:每次都从新读取资源包以后当即释放包,将Instantiate出来的角色放在场景上。这种作法很简洁不会引发内存泄漏,可是对于mmo rpg而言,场景上常常会有不少相同角色。每次从新读取的资源包都会产生独立的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()或者其余相似接口才能删除。

  • 正确的资源彻底释放方法:AssetBundle.Unload(true)——释放AssetBundle和Asset-Object,然后Object.Destroy()释放Cloned-Object。

3. 场景管理

导出场景只能用BuildStreamedSceneAssetBundle,不能使用BuildAssetBundle。场景文件仍然能够用CreateFromMemory读取,只不过Clone的时候必须使用Application.LoadLevel。并且LoadLevel过程和结果貌似不可控,好比你从程序上并不能获得“场景加载完毕”或者“场景的内容是什么”这样的信息。


编译链接和发布

参考

两生花:Unity3d中使用log4net

里面提到C#进行本地配置的问题,看不大懂先挂着,有时间再去研究

http://www.cnblogs.com/koalaylj/articles/2670629.html

相关文章
相关标签/搜索