unity资源管理

看100遍也记不住,画..




整理下

Assetbundle

首先说下Assetbundle,感觉这一个词有2个意思


1 通过BuildAssetBundle打出的.unity3d文件是就是Assetbundle文件,姑且叫资源Assetbundle文件吧

2 然后从打包AssetBundle文件中读取出来一些二进制,需要有一个中间结构管理这个二进制流,这个用来管理的也叫AssetBundle(通过www.assetbundle或Assetbundle.CreateFromMemory从二进制流中获取),姑且叫引用AssetBundle(这个结构是个struct,只是一个引用,占用较少内存)


web stream(二进制)分为3部分  

1压缩assetbundle 

这部分的释放分2种 

如果是从www加载的,www=null或www.dispose时会被释放。

如果是从打包Assetbundle中导入的二进制bytes[]载入的,当找到引用Assetbundle后这个原始压缩二进制就没用了,立刻释放bytes[]=null就可以了,释放掉的是压缩assetbudle的二进制资源,解压后的资源一定还在内存中。


2解压后assetbundle  

这里是Texture,mesh等资源的二进制原始形式。

这部分当引用计数为0时自动释放,而对其引用的正是引用Assetbundle,引用Assetbundle被卸载引用就减1


3 引用assetbundle(一个映射结构,占用较少内存)


创建

1 www方式

www.assetbundle 

具体方法,注意用www加载加载的是压缩的资源Assetbundle,并且路径要加file://(相对于CreateFromFile的path而言 ,并且是在PC上,其他平台没试)

IEnumerator tw(){
		WWW w = new WWW("file://"+path);
		yield return w;
		ab = w.assetBundle;
		if(ab==null)Debug.Log("ab shit!");
		else Debug.Log("ab ok!");
	}

	StartCoroutine(tw());




CreateFromFile:

这种方式不会把整个硬盘AssetBundle文件都加载到内存来(得到引用assetbundle时内存基本不会增加),而是类似建立一个文件操作句柄和缓冲区,需要时才实时Load,所以这种加载方式是最节省资源的,基本上AssetBundle本身不占什么内存,但要特别注意,这个方法需要使用未压缩的资源Assetbundle包

就是说打包时用

BuildPipeline.BuildAssetBundle(obj,null, savePath,BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.UncompressedAssetBundle,BuildTarget.StandaloneWindows);

替换

BuildPipeline.BuildAssetBundle(obj,null, savePath,BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets,BuildTarget.StandaloneWindows);


3 Assetbundle.CreateFromMemory(读取二进制)

等方式获取引用Assetbundle,这个方法优点是方便对二进制做加密

这里有点小坑,这种获取方法具体方式为

AssetBundleCreateRequest abcr = AssetBundle.CreateFromMemory(ba);
AssetBundle assetBundle = abcr.assetBundle;


然后可以用

UnityEngine.Object obj = assetBundle.mainAsset

单独打包(每个资源打成单独的资源Assetbundle文件)时一般可以用这个方法,打包代码为

UnityEngine.Object[] selection = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.DeepAssets);
foreach (UnityEngine.Object obj in selection){
	bool ret=  BuildPipeline.BuildAssetBundle(obj,null, savePath,BuildAssetBundleOptions.CollectDependencies|BuildAssetBundleOptions.CompleteAssets,BuildTarget.StandaloneWindows);
}

说下BuildPipeline.BuildAssetBundle()的参数

这里第一个参数obj(UnityEngin.Object类型)是主要资源,方便通过引用Assetbundle.mainAsset获取的资源

第二个参数是打包时的全部资源,是UnityEngin.Object[]类型,上面这个参数写的null因为是单独打包,也可以按下面写,把所有资源打到一个资源AssetBundle包中

Object[] SelectedAsset = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets);
if (BuildPipeline.BuildAssetBundle (null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies)) {
	AssetDatabase.Refresh ();
} 

assetBundle.load(),assetBundle.loadAsync()通过资源名来载入具体的asset(资源)




卸载


调用assetbundle.unload(false)其实就是把这个assetbundle的引用减1(并且仅仅是引用减1,所以说其实assetbundle.unload(false)这个调用只释放了引用assetbundle这个struct,并没有直接释放其他任何资源)

assetbundle.unload(true)除了unload(false)的功能,还卸载了从引用assetbundle中创建出的aseet,个人感觉assetbundle.unload(true)完全可以被Resource.UnloadAsset(obj)加assetbundle.unload(false)替换掉,没必要用



从引用Assetbundle中获取的Asset(资源)

UnityEngine.Object类型

单独打包用UnityEngine.Object obj = assetBundle.mainAsset获取Asset资源

多资源打包用assetBundle.load获取Asset资源

这里的asset资源就是Texture,mesh,Audio等真正游戏中用到的资源

这些资源实际是资源assetbundle文件解压后二进制文件的引用(一张图Texture,在非依赖打包的情况下,被同时打进多个资源Assetbundle中,那么这些Assetbundle被加载后Texture实际在内存中有多个副本,所以需要依赖打包来解决同一资源多个副本的问题)


使用Resource.UnloadAsset(obj) Resource.UnloadAllUnusedAssets()来卸载

assetbundle.unload(true)也可以卸载Asset


通过Instantiate实例化出的GameObject

通过GameObject.Destroy()来释放


Prefab

prefab的原理与assetbundle类似


加载方式

Resource.Load();这个过程其实 就是从一个缺省打进程序包里的 AssetBundle 里加载资源

实例化


Instaniate一个Prefab,是一个对Assets进行Clone(复制)+引用结合的过程
Gameobject是新Clone出来的,其他资源mesh ,texture,audio等是引用
对一个Prefab重复instaniate时,GameObject每次都Clone出新的,而其他asset资源都是对Resource.Load创建出的缺省AssetBundle中asset的引用


存在3种加载prefab的方式:
1是静态引用,建一个public的变量,在Inspector里把prefab拉上去,用的时候instantiate
2是Resource.Load,Load以后instantiate
3是AssetBundle.Load,Load以后instantiate
三种方式有细节差异,前两种方式,引用对象texture是在instantiate时加载,而assetBundle.Load会把perfab的全部 assets都加载,instantiate时只是生成Clone。所以前两种方式,除非你提前加载相关引用对象,否则第一次instantiate时会 包含加载引用类assets的操作,导致第一次加载的lag。

卸载


总结

assetbundle中内存的占用情况


1 压缩的资源assetbundle占用(内存占用量高),在获取到引用assetbundle后立刻手动释放


2 解压资源assetbundle 的解压buffer占用,unity负责自动释放


3 解压后的资源assetbundle(asset资源的原始二进制)占用(内存占用量高),这个只有引用为0时unity负责自动释放,减少引用就是unload 引用assetbundle


4 引用assetbundle(一个struct,用来引用解压后的资源assetbundle二进制)(内存占用少),一旦从这个引用assetbundle获取到asset文件,就可以手动清理掉,减少引用计数,而一旦引用数为0,解压后的资源assetbundle就被释放了,所以释放这个引用assetbundle很重要


5 UnityEngine.Object类型(具体类型为Texture,mesh,audio等)的asset(资源)对象 内存占用量高):

如果asset来源是本地,使用Resource.Load加载

asset是非prefab,Resource.Load后,会分配Asset内存

asset是prefab,Resource.Load后,不会分配Asset内存,Instaniate后才分配,卸载时先GameObject.Destroy(),prefab=null,然后调用Resource.UnloadAllUnusedAssets()


如果asset来源是本地或网络的资源Assetbundle文件

asset是非prefab,assetBundle.LoadAsset()后,会分配Asset内存

asset是prefab,assetBundle.LoadAsset()后,会分配prefab相关的所有asset内存,而instaniate时只新创建Go,卸载时先GameObject.Destroy(),prefab=null,然后调用Resource.UnloadAllUnusedAssets()


Resource.UnloadAllUnusedAssets()最好配合GC.Collect();使用


如果同一个asset被打入两个不同的assetbundle包,那么从这两个包中载出的asset不是用一个引用,所以打包要用依赖包,把共享资源放在一起,给其他资源依赖,减少统一资源占用多份内存


6 实例化出的GameObject对象(内存占用少),不需要GameObj时销毁或者放入空闲对象池进行重复利用,避免频繁创建销毁


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值