一、AssetBundle的管理类:
public class AssetBundleLoaderMgr
{
/// <summary>
/// 初始化,加载AssetBundleManifest,方便后面查找依赖
/// </summary>
public void Init()
{
string streamingAssetsAbPath = Path.Combine(Application.streamingAssetsPath, "StandaloneWindows");
AssetBundle streamingAssetsAb = AssetBundle.LoadFromFile(streamingAssetsAbPath);
m_manifest = streamingAssetsAb.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
}
/// <summary>
/// 加载AssetBundle
/// </summary>
/// <param name="abName">AssetBundle名称</param>
/// <returns></returns>
public AssetBundle LoadAssetBundle(string abName)
{
AssetBundle ab = null;
if (!m_abDic.ContainsKey(abName))
{
string abResPath = Path.Combine(Application.streamingAssetsPath, abName);
ab = AssetBundle.LoadFromFile(abResPath);
m_abDic[abName] = ab;
}
else
{
ab = m_abDic[abName];
}
return ab;
}
/// <summary>
/// 从AssetBundle中加载Asset
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <param name="abName">AssetBundle名</param>
/// <param name="assetName">Asset名</param>
/// <returns></returns>
public T LoadAsset<T>(string abName, string assetName) where T : Object
{
AssetBundle ab = LoadAssetBundle(abName);
T t = ab.LoadAsset<T>(assetName);
return t;
}
/// <summary>
/// 缓存加载的AssetBundle,防止多次加载
/// </summary>
private Dictionary<string, AssetBundle> m_abDic = new Dictionary<string, AssetBundle>();
/// <summary>
/// 它保存了各个AssetBundle的依赖信息
/// </summary>
private AssetBundleManifest m_manifest;
/// <summary>
/// 单例
/// </summary>
private static AssetBundleLoaderMgr s_instance;
public static AssetBundleLoaderMgr instance
{
get
{
if (null == s_instance)
s_instance = new AssetBundleLoaderMgr();
return s_instance;
}
}
}
二、AssetBundle调用类:该脚本需要挂载在场景中的某个物体上,且需要输入标签名和预制体名。
public class LoadAb : MonoBehaviour
{
[Header("标签名:")]
public string assetBundle;
[Header("预制体名:")]
public string prefabName;
void Awake()
{
//初始化
AssetBundleLoaderMgr.instance.Init();
}
void LoadAsset()
{
//加载预设
GameObject prefab = AssetBundleLoaderMgr.instance.LoadAsset<GameObject>(assetBundle, prefabName);
//实例化预设
Instantiate(prefab);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.S))
{
LoadAsset();
}
}
}
三、资源复用
实际项目中会有多个预制体重复的部分,单独压缩浪费资源,所以需要将共同部分作为一个AssetBundle进行压缩。这样其它不同的部分就会对共同部分产生依赖。在做动态加载时,需要把依赖加载上,防止资源丢失。假设依赖资源是res。
为加载完整,需要在AssetBundleLoaderMgr脚本中加上加载依赖的代码。
public AssetBundle LoadAssetBundle(string abName)
{
AssetBundle ab = null;
if (!m_abDic.ContainsKey(abName))
{
string abResPath = Path.Combine(Application.streamingAssetsPath, abName);
ab = AssetBundle.LoadFromFile(abResPath);
m_abDic[abName] = ab;
}
else
{
ab = m_abDic[abName];
}
//加载依赖
string[] dependences = m_manifest.GetAllDependencies(abName);
int dependenceLen = dependences.Length;
if (dependenceLen > 0)
{
for (int i = 0; i < dependenceLen; i++)
{
string dependenceAbName = dependences[i];
if (!m_abDic.ContainsKey(dependenceAbName))
{
AssetBundle dependenceAb = LoadAssetBundle(dependenceAbName);
m_abDic[dependenceAbName] = dependenceAb;
}
}
}
return ab;
}