AssetBundle打包和各种加载方式
1:什么是AssetBundle。
AssetBundle是从unity项目中打包出来的资源文件,可用于资源的更新等。AssetBundle支持3中格式的压缩选择,分别是LZMA,LZ4,无压缩。默认是LZMA格式的压缩,但是这样虽然可以使资源文件大小大大缩小,利于下载,但是也有不利的一面,在使用时会先解压再使用,所以会造成加载时间过长。
不压缩格式资源包会比较大,但是加载时不需要解压,所以加载时会更快。
2:怎么创建AssetBundle.
在unity5.x中资源打包已经大大优化,打包过程比unity4.x大大简化。可以自动打出依赖包。打包的过程有两种,第一种是给要打包的资源起一个名字。如下图
默认是不打包的,起名字后变为
当想把多个物体打到一个包里时,只需把多个物体设置成相同包名即可。设置好包名后,打包就容易的多了,打包代码如下:(注意,在运行此脚本之前,您需要在Assets文件夹中创建“AssetBundles”文件夹)
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem (“Assets/Build AssetBundles”)]
static void BuildAllAssetBundles ()
{
BuildPipeline.BuildAssetBundles (“Assets/AssetBundles”, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSXUniversal);
}
}
生成AssetBundle的时候每个文件会多生成一个Manifest文件,每个文件多生成的Manifest 文件是不需要的,其作用就是供开发人员查看AssetBundle 中的依赖关系等信息。但除了每个文件多生成的 Manifest 以外,根目录下还会有一个与根目录同名的AssetBundle 以及 Manifest 文件,通过运行时加载这个AssetBundle,可以得到一个 AssetBundleManifest 对象,然后就可以通过这个对象得到AssetBundle直接的依赖关系。在AssetBundle打包时,只打包这个Prefab(不指定BuildAssetBundleOptions.CompleteAssets和BuildAssetBundleOptionsCollectDependencies)的话是不能正确实例化的,因为AssetBundle中的资源和Resource文件夹下资源是不会建立依赖关系的(脚本除外,因为开启BuildAssetBundleOptionsCollectDependencies 时,脚本依然不会打包到AssetBundle中)。所以会出现Mesh、Material等的丢失。
注意:
如果你只是给预制体起了名字而没有给预制体依赖的资源起名字的话,打出来的包就会把依赖的资源默认跟预制体打包到同一个assetbundle里,这样就造成了如果两个预制体使用同一份贴图资源,那么这个贴图资源就会分别跟两个预制体打包到一起,这就造成了内存的浪费。正确的做法是给贴图资源单独起一个名字,使其打包为一个包,然后预制体再分别打包,这样就会发现预制体的assetbundle包大大减小。但是,这样的话还有一个问题,就是每次要先加载依赖的资源,然后才能加载实例化。
3:如何加载资源。
要加载一个资源A,必须先去加载它的所有依赖资源,要知道这个资源A依赖了哪些资源,必须先去加载AssetBundleManifest,通过AssetBundleManifest对象的GetAllDependencies(A)方法,获取它依赖的所有资源。
依赖资源都加载了,就可以去真正加载资源A了。否则加载出来的物体就会材质丢失。
注意点:
1.资源A加载完了后,要记得Unload(false),资源A的依赖资源要在 资源A加载完成后,才能Unload(false),否则无法正常加载资源A
2.不Unload的话也可以,那就自己做一个字典记录所有加载过的AssetBundle,还有它们的引用计数器。那样就可以先判断是否存在,然后再确定是否要去加载
加载的方式分为两种,一种是从文件加载,一种是从网络加载。各种情况的加载如下;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Loadassert : MonoBehaviour
{
string BundleURL = "file:///E:/Unity3D/modelpeizhi/Assets/AssetBundles/earth";
string AssetName = "earth";
//从文件夹里加载一个异步加载
public void LoadOne()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/Sphere");
AssetBundleRequest gObject = bundle.LoadAssetAsync("sphere", typeof(GameObject));
GameObject obj = gObject.asset as GameObject;
Instantiate(obj);
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
}
//从文件夹里加载一个同步加载
public void LoadNoRequest()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/Sphere");
UnityEngine.Object obj = bundle.LoadAsset("sphere");
Instantiate(obj);
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
}
//从文件夹里加载全部
public void loadAll()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/Sphere");
foreach (UnityEngine.Object temp in bundle.LoadAllAssets())
{
Instantiate(temp);
}
bundle.Unload(false);
}
//从文件夹里通过依赖关系加载
public void LoadManifest()
{
//加载那个打包时额外打出来的总包
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/AssetBundles");
// var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/AssetBundles.manifest");//不能这样加载manifest。
AssetBundleManifest manifest = bundle.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
//AssetBundleManifest不是某个文件的名字,是固定的一个东西
string[] deps = manifest.GetAllDependencies("earth");
//earth是打出的包名
List<AssetBundle> depList = new List<AssetBundle>();
Debug.Log(deps.Length);
for (int i = 0; i < deps.Length; ++i)
{
AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/" + deps[i]);
depList.Add(ab);
}
AssetBundle cubeAb = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/earth");
GameObject org = cubeAb.LoadAsset("earth") as GameObject;
Instantiate(org);
cubeAb.Unload(false);
for (int i = 0; i < depList.Count; ++i)
{
depList[i].Unload(false);
}
bundle.Unload(true);
}
public void LoadNoManifest()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/earth11");
AssetBundleRequest gObject = bundle.LoadAssetAsync("earth11", typeof(GameObject));
GameObject obj = gObject.asset as GameObject;
Instantiate(obj);
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
}
public void loadWWWNoStored()
{
StartCoroutine(_loadWWWNoStored());
}
public void LoadWWWStored()
{
StartCoroutine(_LoadWWWStored());
}
/// <summary>
/// -变量BundleURL的格式–如果为UnityEditor本地:
/// —“file://”+“application.datapath”+“/文件夹名称/文件名”
/// –如果为服务器: —http://….
///-变量AssetName:
///–为prefab或文件的名字。
/// </summary>
public IEnumerator _loadWWWNoStored()
{
// Download the file from the URL. It will not be saved in the Cache
using (WWW www = new WWW(BundleURL))
{
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
Instantiate(bundle.LoadAsset(AssetName));
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
public IEnumerator _LoadWWWStored()
{
// Wait for the Caching system to be ready
while (!Caching.ready)
yield return null;
// Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
using (WWW www = WWW.LoadFromCacheOrDownload(BundleURL, /*version*/ 0))
{
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
// Instantiate(bundle.mainAsset);
// Instantiate(bundle.LoadAsset(AssetName));
foreach (UnityEngine.Object temp in bundle.LoadAllAssets())
{
Instantiate(temp);
}
// Instantiate(bundle.LoadAllAssets());
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
}
- 上一篇: MySQL数据库优化(八)——MySQL负载均衡 & 读写分离
- 下一篇: MD5信息摘要算法