AssetBundle的加载

来源:互联网 发布:java调用api接口实例 编辑:程序博客网 时间:2024/06/06 01:38

AssetBundle怎么样去加载?

AssetBundle在本地的话我们一般都放在StreamingAssets目录下,为什么要放在StreamingAssets下面?

这个文件夹在安卓手机平台一般是只可读不可写的,在安卓平台,有这么一个路径apk\Assets,它是不可写的,在我们打包发布成apk的时候,它会把我们这个StreamingAssets文件夹下面的东西打包在apk\Assets文件夹下面。

Unity有这么一个路径Persistent,这个文件夹是可读可写的,一般的程序第一次加载的时候,把StreamingAssets文件夹下面的东西拷贝到Persistent文件夹。

1. 对于移动平台,也就是手机上AssetBundle一般从本地加载的话,都会放在这个Persistent路径下面去,

2. 如果从服务器下载的话,会通过WWW方式,从服务器down下来,直接放在Persistent路径下面。

3. 这是手机上的硬盘上的一个文件夹,你手机要能识别的话,首先第一件事,你得把它加载到内存里面,一般是这么一个流程:

流程

1,如果我们这个包本身就在硬盘上,从硬盘加载到内存。

  对应代码:AssetBundle.CreateFromFile(string path);

  文件的卸载:

1.1 assetbundle.unload(false)   只是卸载的内存文件

1.2 Assetbundle.unload(true)   卸载的是 内存文件和assetbundle.load出来的文件。

2,WWW加载出来之后就是一个assetbundle,然后通过assetbundle.load步骤就好比解包(解压缩包)。Assetbundle.load是进行的io操作。

   2.1 我们如果只想对assetbundle.load出来的东西进行释放,使用这个api-==>Resources.UnloadAsset(obj)进行释放,比如说我们首先卸载了内存,没有卸载assetbundle.load出来的东西,就要使用这个api进行卸载。

  2.2 对于一些隐藏的文件,要使用Resources.UnLoadUnuseAsset()进行释放,比如说:我们要去释放一个material,可是它本身会依赖一些图片,我们如果只是Resources.UnLoadAsset(material),只会把这个material单独释放掉,可是跟它关联的一些image却并没有释放,这部分我们是无法预判的,我们并不知道这个material上有哪些图片,也不在我们的关注范围,所以它对我们来说是隐藏文件,那么这部分隐藏文件也得释放掉,那么这个时候,主角出场,也就是Resources.UnLoadUnuseAsset(),它会帮我们把这部分隐藏文件释放掉。

 

   如果我说的不够通俗,那么我在这里再来解释一下隐藏的文件:比如说 加载test.prefab,

这个prefab依赖的材质和纹理,都称为隐藏文件。

3,程序要使用,

   3.1 如果是图片这样的资源,assetbundle.load出来的object对象直接使用

  释放如同2.1

   3.2 如果是prefab这样的资源,必须要用Instantiate实例化一下

  释放使用Destroy

 

AssetBundle 的依赖关系:

通过一个例子了解一下。下面是我的文件结构和对资源进行打包后的assetbundle文件结构图。

 

 

通过图片我们可以看到,我们每次打包出来的assetbundle都会有一个相应的.manifest的文件,这个文件包含了我们这个文件的一些依赖关系。

我们打开AssetBundle.manifest,如下图:

 

 

 

可以看到我这个路径里面有四个assetbundle文件以及每个文件的名字,还包括依赖项,比如说dependency

可以了解到:

cube依赖于red.mt这个材质。

red.mt又依赖于bg.image这张图片。

bg.image没有依赖项。

这里我说一下打包的注意事项,我们打包的时候,不仅仅是要放每个界面的预制件,还要把这个界面用到的图集,材质,纹理,贴图等等,都放在对应的路径下面进行打包。这样这里的依赖项才会获取到对应的文件。不然就是空。

我这里login就是单独把prefab进行了打包,而没有把它的材质,贴图文件夹进行assetbundle标记名字,所以它并没有获取到依赖项。

     ===============================================================================================

掌握了以上的知识点,然后往下看。

Assetbundle 的加载流程:

1. 先加载依赖的assetbundle

2. 再加载自己的assetbundle

Assetbundled的卸载流程:

1. 先要卸载自身的assetbundle

2. 在卸载依赖的assetbundle

通过一个例子了解一下加载和卸载关系。

assetbundleA依赖于assetbundleBassetbundleC,assetbundleBassetubndleC都依赖于assetbundleD

(正常情况下)

1.在这种依赖关系下加载A顺序是  D=>B,C=>A

2.在这种依赖关系下卸载A的顺序:A=>B,C=>D

3.在这种依赖关系下卸载B的顺序是:只卸载B的依赖关系,不会卸载B,不用卸载其他,原因在于其他还有依赖关系。

4.那么在卸载完B之后,如果继续卸载C,卸载顺序是

先卸载C的依赖关系,然后发现D没有依赖了,然后卸载D,C不会卸载,因为A还依赖于BC

5.如果继续卸载A,卸载顺序,先卸载A的依赖关系,之后发现BC都没有依赖了,所以需要卸载BC,最后卸载A

那么在我们的项目中,这种没有引用的依赖关系系统是不会帮我们卸载的,而是需要我们自己去写这么一套卸载逻辑。把没有引用的assetbundle自动卸载掉。

程序中需要注意的是 A需要记载它依赖的谁,B,C需要记录它被谁依赖的。

 

加载的时候注意事项:

  比如说有个assetbundleA

       它里面包含objA,objB,objC

      我们第一次加载objA,可以调用assetbundle.load

第二次加载objA,还是调这个方法么,不是,这里我们一般第一次把它添加到缓存中,以后用的时候直接从缓冲里面去取。

 

 

 

 

 

 

总结

1. 获取依赖配置关系。

1.1 都是从manifest文件中获取。

1.2 程序实现

使用www加载方式。

WWW mainfest=new WWW(manifestPath);

mainfest.assetbundle.loadasset(“AssetBundleManifest”)

这里参数 AssetBundleManifestunity官方定死的。

1.3整个程序 只用加载一次

2. 根据 名称找到目标加载资源的所有依赖。

Name 包名 ==>sceneone/login

主要是为上层提供查找方便。

3. 根据依赖关系加载资源。

4. 加载我们的assetbundle

  WWW bundle=new WWW(bundlePath);

5. 加载资源

AssetBundle.LoadAsset(resName); //加载单个资源

AssetBundle.LoadAssetWithSibAssets(resName) //加载多个资源,当一个资源里面包含多个obj的时候使用。

 

 

整个场景我们该如何去加载和配置?

下面是整个模块的设计流程图

我们在每个scene文件夹下面有一个该scene各个资源与assetbundle的对应关系的配置文件。

1. 先找到每个scene文件夹的配置文件获取其对应的assetbundle的包名

2. assetbundle包名交给assetbundleManager让其把映射关系管理起来

3. 每个scene资源有自己assetbundle里面的依赖关系管理器

4. 根据assetbundleManager获取各个assetbundle包名,然后根据包名加载包

5. 每个assetbundle包含的资源加载流程



代码实现待续...后续会传到git上面。

assetbundle这块内容比较多,涉及到很多知识点,一直在看官方的介绍,也一直在整理,写的有点累,只能慢慢修改了。

 

原创粉丝点击