一、什么是AssetBundle?
1.它存在于硬盘上的文件。可称之为压缩包。该压缩包里面有多个文件,这些文件可分为两类:serialized file和resources file(即序列化文件和源文件)。(1)serialized file:资源被打散放在一个对象中,最后统一被写进一个单独的文件(只有一个)(如:模型资源,prefab资源等)(2)resources file:某些二进制资源(如:图片、声音)被单独保存,方便快速加载。
2.它是一个AssetBundle对象,我们可以通过AssetBundle类从压缩包加载出来对象并使用,这个对象包含了所有当初添加到这个压缩包里面的内容。
下面是整理的缓存加载机制
public class LoadAssetBundle : MonoBehaviour
{
public class CacehDependencies
{
public CacehDependencies(int _index, AssetBundle _assetBundle)
{
index = _index;
assetBundle = _assetBundle;
}
public int index;
public AssetBundle assetBundle;
}
List<CacehDependencies> cacehDependencies = new List<CacehDependencies>();
/// <summary>
/// 若加载路径与打包路径不同,用这个
/// </summary>
/// <param name="filePath"></param>加载路径
/// <param name="manifestBundleName"></param>须指定要加载的manifestAssetBundle
/// <param name="abFileName"></param>要加载的ab
/// <param name="prefabFileName"></param>预制体 无后缀
public GameObject loadAssetBundleFiles(string filePath, string manifestBundleName, string abFileName, string prefabFileName)
{
/**
* 1.首先从打包路径获取依赖
* 这里加载的就是生成的同名文件ab
*/
AssetBundle manifestBundle = AssetBundle.LoadFromFile(getManifestFilePath(filePath, manifestBundleName));
/**
* 2.获取依赖资源列表
*/
if (manifestBundle != null)
{
try
{
AssetBundleManifest manifest = manifestBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//固定加载方式,通过 assetbundle Abs加载Abs.manifest
manifestBundle.Unload(false);
//获取加载ab的依赖信息,参数为ab名称,如cube.ab
LoadDependencies(manifest, filePath, abFileName);
}
catch (InvalidCastException e)
{
Debug.LogException(e);
}
/**
* 3.最后加载ab
* 注意这里的LoadAsset的参数是Prefab的名称,无后缀,如cube而非cube.ab或cube.prefab
*/
AssetBundle ab = AssetBundle.LoadFromFile(generateAbsoluteFile(filePath, abFileName));
GameObject go = ab.LoadAsset(prefabFileName) as GameObject;
ab.Unload(false);
return go;
}
return null;
}
private void LoadDependencies(AssetBundleManifest manifest, string filePath, string abFileName)
{
string[] dependsFile = manifest.GetAllDependencies(abFileName);
if (dependsFile.Length > 0)
{
//根据获取到的依赖信息加载所有依赖资源ab
AssetBundle[] dependsBundle = new AssetBundle[dependsFile.Length];
for (int i = 0; i < dependsFile.Length; i++)
{
CacehDependencies cacehDependencies = GetContain(dependsFile[i]);
if (cacehDependencies == null)//如果缓存没有依赖资源就再去加载
{
string fp = generateAbsoluteFile(filePath, dependsFile[i]);
Debug.Log(string.Format("depends:{0}:{1}", i, dependsFile[i]));
dependsBundle[i] = AssetBundle.LoadFromFile(fp);
CacehDependencies cacehDependencie = new CacehDependencies(1, dependsBundle[i]);
}
else //将依赖资源放入缓存中,加载一次资源缓存计数加一
{
cacehDependencies.index += 1;
}
}
}
}
private CacehDependencies GetContain(string name)
{
for (int i = 0; i < cacehDependencies.Count; i++)
{
if (cacehDependencies[i].assetBundle.name.Equals(name))
{
return cacehDependencies[i];
}
}
return null;
}
//每十分钟遍历一次
public void GCCacehDependencies()
{
for (int i = 0; i < cacehDependencies.Count; i++)
{
if (cacehDependencies[i].index == 0)//如果计数等于0就卸载依赖资源
{
cacehDependencies[i].assetBundle.Unload(false);
}
else
{
cacehDependencies[i].index -= 1;//如果计数大于0就计数减一
}
}
}
/// <summary>
/// 若打包路径和加载路径相同则使用这个
/// </summary>
/// <param name="filePath"></param>打包路径和加载路径
/// <param name="abFileName"></param>加载ab文件名称
/// <param name="prefabFileName"></param>加载预制体 无后缀
public GameObject loadAssetBundleFiles(string filePath, string abFileName, string prefabFileName)
{
return loadAssetBundleFiles(filePath, "", abFileName, prefabFileName);
}
private string getManifestFilePath(string filePath, string manifestName)
{
if (string.IsNullOrEmpty(manifestName)) /*路径*/
{
int lastSymbol = filePath.LastIndexOf('/');
string pathAssetBunldeName = filePath.Substring(lastSymbol);
return (filePath + pathAssetBunldeName).Trim();
}
else //name
{
return filePath + "/" + manifestName;
}
}
private string generateAbsoluteFile(string filePath, string fileName)
{
return string.Concat(filePath, "/", fileName).Trim();
}