Unity AssetBundle 基础操作
代码很简单没有难度,都有注解,随便 康一康 就会了。
菜单编辑 按钮点击 构建 AssetBundle 包集
有一点需要注意:CreateAssetBundle_ZH 脚本需要安置在Asset 下 Editor文件夹下
不然无法正确执行
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
/// <summary>
/// 菜单编辑 按钮点击
/// </summary>
//[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class CreateAssetBundle_ZH : MonoBehaviour //ScriptableObject
{
//菜单栏 Button 创建
[MenuItem("AssetBundles/Build AssetBundles")]
static void BuildAllAssetBundles()
{
//AssetBundle 存储路径
string _AssetBundleDirectory = Application.streamingAssetsPath + "//AssetBundles";//Application.dataPath + "/Resources";
//IO 构建
if (!Directory.Exists(_AssetBundleDirectory))
{
Directory.CreateDirectory(_AssetBundleDirectory);
}
//构建编辑中指定的所有资产包 变量( 构建地址、 资产包构建选项、目标构建平台)//ChunkBasedCompression
BuildPipeline.BuildAssetBundles(_AssetBundleDirectory, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
#if UNITY_EDITOR
//资源刷新
AssetDatabase.Refresh();
#endif
}
}
正确放置之后就需要对你要使用的资源进行分包处理了
比如我这个:我对当前 Cube 把它放在了 model 里面这个AB包集里
AB包集名字 是自己取得 如果你没有就自己 New 一个
注意:如果你要使用的资源没有赋予 AB包集的话 是没有办法生成AssetBundle 文件的
点击菜单栏 AssetBundles按钮下的Build AssetBundles 按钮就可以生成你自己的AssetBundle文件了
AssetBundle 基础功能
AssetBundle 加载:需要注意AB 包加载需要填写对的路径以及包集名字(小写)
正确加载 AB 包集后可以使用 LoadAsset() 方法加载当前包集中的具体资源
注意拿到具体资源后需要实例化 不然你就只是拿到
当前 AB 包集使用完毕之后注意 卸载 不然会报错
因为 AB 包的特性就是无法重复加载
AssetBundle 包集
AssetBundle.LoadAsset() 默认返回值是Object 类型
这个就是主包中固定文件里的内容:里面包含了各个 AB 包集 的依赖关系
//主包中固定文件的标准写法
AssetBundleManifest _AssetBundleManifest = _AssetBundleMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
AssetBundle 没有依赖项 加载
/// <summary>
/// AssetBundle 没有依赖项的加载
/// </summary>
public void LoadAssetBundle()
{
//AB 包集加载 LoadFromFile方法里面的参数是 指定到文件的详细路径
AssetBundle _AssetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/AssetBundles/"+ "model");
//加载 AssetBundle 包体中的资源
//使用名字加载 可能会出现同名但是资源类型不同的情况
//注意加载 资源名称是根据填写的名字 全部都是小写
//AssetBundle 无法重复加载 否则报空
//两种加载方式 交易使用第二种 带指定类型的因为可以避免 加载资源时 同名不同类型的文件
//但是也要看具体情况具体使用 随君意
GameObject _Gam = _AssetBundle.LoadAsset<GameObject>("SphereModel") ;
GameObject _Gam02 = _AssetBundle.LoadAsset("CubeModle", typeof(GameObject)) as GameObject;
//实例化
Instantiate(_Gam);
Instantiate(_Gam02);
//AB 包集卸载
//false 只卸载AB 包集 但是不卸载资源
//true 卸载AB 包集 同时也卸载资源
//避免重复加载报空
_AssetBundle.Unload(false);
}
AssetBundle 没有依赖项 异步加载
/// <summary>
/// 异步加载 AssetBundle
/// </summary>
/// <param AB包集 名字="_AssetBundleName"></param>
/// <param AB包集中资源名字="_PrefabName"></param>
/// <returns></returns>
public IEnumerator LoadAssetBundle(string _AssetBundleName,string _PrefabName)
{
//加载 AB集
AssetBundleCreateRequest _AssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/AssetBundles/" + _AssetBundleName);
//等待返回
yield return _AssetBundleCreateRequest;
//资源加载
AssetBundleRequest _Abr = _AssetBundleCreateRequest.assetBundle.LoadAssetAsync(_PrefabName,typeof(GameObject));
//默认类型为 Object 所以需要转换一下
GameObject _Gam = _Abr.asset as GameObject;
Instantiate(_Gam);
//卸载所有当前加载的资源包
//false 只卸载AB 包集 但是不卸载资源
//true 卸载AB 包集 同时也卸载资源
//避免重复加载报空
AssetBundle.UnloadAllAssetBundles(false);
yield return null;
}
AssetBundle 有依赖项 加载
/// <summary>
/// AB包集 资源依赖
/// </summary>
/// <param 主包名字="_AssetBundlesPathName"></param>
/// <param AB包子集="_AssetBundlesName"></param>
/// <param 预制体 名字="_PrefabName"></param>
public void LoadAssetBundleDepend(string _AssetBundlesPathName, string _AssetBundlesName, string _PrefabName)
{
//加载主包
AssetBundle _AssetBundleMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/AssetBundles/" + _AssetBundlesPathName);
//加载主包中的固定文件
AssetBundleManifest _AssetBundleManifest = _AssetBundleMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
//从固定文件中得到依赖信息
//得到你想要知道 当前AB包集中的所有依赖
string[] _DependStr = _AssetBundleManifest.GetAllDependencies(_AssetBundlesName);
//如果有依赖包的话
if (_DependStr.Length > 0)
{
AssetBundle _NewAssetBundle = null;
for (int j = 0; j < _DependStr.Length; j++)
{
//依赖包加载
_NewAssetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/AssetBundles/" + _DependStr[j]);
}
//如果 AB 包集不为空
if (_NewAssetBundle != null)
{
//AB包 子级资源加载
AssetBundle _NewAssetBundleSubset;
_NewAssetBundleSubset = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/AssetBundles/" + _AssetBundlesName);
//GameObject _Gam = _NewAssetBundleSubset.LoadAsset<GameObject>(_PrefabName);
GameObject _Gam = _NewAssetBundleSubset.LoadAsset(_PrefabName, typeof(GameObject)) as GameObject;
Instantiate(_Gam);
}
}
else
{
//如果没有依赖包就正常加载
AssetBundle _NewAssetBundleSubset;
_NewAssetBundleSubset = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/AssetBundles/" + _AssetBundlesName);
//资源加载
//GameObject _Gam = _NewAssetBundleSubset.LoadAsset<GameObject>(_PrefabName);
GameObject _Gam = _NewAssetBundleSubset.LoadAsset(_PrefabName, typeof(GameObject)) as GameObject;
Instantiate(_Gam);
}
}
AssetBundle 卸载
//两种方法
//AB 当前包集卸载
//false 只卸载当前AB 包集 但是不卸载资源
//true 卸载当前AB 包集 同时也卸载资源
//_AssetBundle 是当前加载的 AB 包集
_AssetBundle.Unload(false);
//卸载所有当前加载的资源包
//false 只卸载所有AB 包集 但是不卸载资源
//true 卸载所有AB 包集 同时也卸载资源
AssetBundle.UnloadAllAssetBundles(false);
AssetBundle 包管理器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// AssetBundle 包管理器
/// </summary>
public class AssetBundleManager_ZH : MonoBehaviour
{
//单例
public static AssetBundleManager_ZH _AssetBundleManager;
//AssetBundle 主包
private AssetBundle _AssetBundleMain = null;
//依赖包配置文件
private AssetBundleManifest _AssetBundleManifest = null;
//AB包集字典 存储已经加载的AB包
//key AB 包名字 value AB包
private Dictionary<string, AssetBundle> _AssetBundleDic = new Dictionary<string, AssetBundle>();
/// <summary>
/// AssetBundle主包 加载路径
/// </summary>
public string _AssetBundlePath
{
get
{
return Application.streamingAssetsPath + "/AssetBundles/";
}
set
{
_AssetBundlePath = value;
}
}
/// <summary>
/// 主包名
/// </summary>
public string _AssetBundleMainName
{
get
{
return "AssetBundles";
}
set
{
_AssetBundleMainName = value;
}
}
private void Awake()
{
_AssetBundleManager = this;
}
#region AssetBundle 资源同步加载
/// <summary>
/// 同步加载 不指定类型
/// </summary>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <returns></returns>
public Object LoadAssetBundleSync(string _AssetBundleName, string _ResName)
{
LoadAB(_AssetBundleName);
Object _AssetBundleObject = _AssetBundleDic[_AssetBundleName].LoadAsset(_ResName);
//实例化
if (_AssetBundleObject as GameObject)
{
return Instantiate(_AssetBundleObject);
}
else
{
//加载 当前 使用资源 AB 包(_AssetBundleName)名为 _ResName 的资源
return _AssetBundleObject;
}
}
/// <summary>
/// 同步加载 指定类型
/// 方便加载资源时 同名不同类型的文件
/// </summary>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <param 指定的类型="_Type"></param>
/// <returns></returns>
public Object LoadAssetBundleSync(string _AssetBundleName, string _ResName, System.Type _Type)
{
LoadAB(_AssetBundleName);
Object _AssetBundleObject = _AssetBundleDic[_AssetBundleName].LoadAsset(_ResName, _Type);
//实例化
if (_AssetBundleObject as GameObject)
{
return Instantiate(_AssetBundleObject);
}
else
{
//加载 当前 使用资源 AB 包(_AssetBundleName)名为 _ResName 的资源
return _AssetBundleObject;
}
}
/// <summary>
/// 同步加载 不指定类型 泛型加载
/// 方便加载资源时 同名不同类型的文件
/// </summary>
/// <typeparam 返回类型="T"></typeparam>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <returns></returns>
public T LoadAssetBundleSync<T>(string _AssetBundleName, string _ResName) where T : Object
{
LoadAB(_AssetBundleName);
T _AssetBundleObject = _AssetBundleDic[_AssetBundleName].LoadAsset<T>(_ResName);
//实例化
if (_AssetBundleObject as GameObject)
{
return Instantiate(_AssetBundleObject);
}
else
{
//加载 当前 使用资源 AB 包(_AssetBundleName)名为 _ResName 的资源
return _AssetBundleObject;
}
}
#endregion
#region AssetBundle 资源异步加载
/// <summary>
/// 根据名字异步加载资源
/// </summary>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <param 委托="_CallBack"></param>
public void LoadResAsync(string _AssetBundleName, string _ResName,UnityAction<Object> _CallBack)
{
StartCoroutine(ReallyLoadResAsync(_AssetBundleName, _ResName, _CallBack));
}
/// <summary>
///异步资源加载
/// </summary>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <param 委托="_CallBack"></param>
private IEnumerator ReallyLoadResAsync(string _AssetBundleName, string _ResName, UnityAction<Object> _CallBack)
{
LoadAB(_AssetBundleName);
AssetBundleRequest _ABR = _AssetBundleDic[_AssetBundleName].LoadAssetAsync(_ResName);
yield return _ABR;
//异步加载结束后 通过委托 传递资源给外部
//实例化
if (_ABR.asset as GameObject)
{
_CallBack(Instantiate(_ABR.asset));
}
else
{
//加载 当前 使用资源 AB 包(_AssetBundleName)名为 _ResName 的资源
_CallBack(_ABR.asset);
}
}
/// <summary>
/// 异步加载 指定类型
/// 方便加载资源时 同名不同类型的文件
/// </summary>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <param 指定的类型="_Type"></param>
/// <param 委托="_CallBack"></param>
public void LoadResAsync(string _AssetBundleName, string _ResName, System.Type _Type,UnityAction<Object> _CallBack)
{
StartCoroutine(ReallyLoadResAsync(_AssetBundleName, _ResName, _Type, _CallBack));
}
/// <summary>
/// 异步资源加载 指定类型
/// </summary>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <param 指定的类型="_Type"></param>
/// <param 委托="_CallBack"></param>
private IEnumerator ReallyLoadResAsync(string _AssetBundleName, string _ResName, System.Type _Type, UnityAction<Object> _CallBack)
{
LoadAB(_AssetBundleName);
AssetBundleRequest _ABR = _AssetBundleDic[_AssetBundleName].LoadAssetAsync(_ResName, _Type);
yield return _ABR;
//异步加载结束后 通过委托 传递资源给外部
//实例化
if (_ABR.asset as GameObject)
{
_CallBack(Instantiate(_ABR.asset));
}
else
{
//加载 当前 使用资源 AB 包(_AssetBundleName)名为 _ResName 的资源
_CallBack(_ABR.asset);
}
}
/// <summary>
/// 异步加载 不指定类型 泛型加载
/// 方便加载资源时 同名不同类型的文件
/// </summary>
/// <typeparam 返回类型="T"></typeparam>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <returns></returns>
public void LoadResAsync<T>(string _AssetBundleName, string _ResName, UnityAction<T> _CallBack)where T:Object
{
StartCoroutine(ReallyLoadResAsync<T>(_AssetBundleName, _ResName, _CallBack));
}
/// <summary>
/// 异步加载 不指定类型 泛型加载
/// 方便加载资源时 同名不同类型的文件
/// </summary>
/// <typeparam 返回类型="T"></typeparam>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
/// <param 需要加载的资源名字="_ResName"></param>
/// <returns></returns>
private IEnumerator ReallyLoadResAsync<T>(string _AssetBundleName, string _ResName, UnityAction<T> _CallBack) where T : Object
{
LoadAB(_AssetBundleName);
AssetBundleRequest _ABR = _AssetBundleDic[_AssetBundleName].LoadAssetAsync(_ResName);
yield return _ABR;
//异步加载结束后 通过委托 传递资源给外部
//实例化
if (_ABR.asset as GameObject)
{
_CallBack(Instantiate(_ABR.asset)as T);
}
else
{
//加载 当前 使用资源 AB 包(_AssetBundleName)名为 _ResName 的资源
_CallBack(_ABR.asset as T);
}
}
#endregion
/// <summary>
/// 主包以及依赖包加载
/// </summary>
/// <param 需要加载的AB 包名字="_AssetBundleName"></param>
public void LoadAB(string _AssetBundleName)
{
//AssetBundle 主包加载
if (_AssetBundleMain == null)
{
_AssetBundleMain = AssetBundle.LoadFromFile(_AssetBundlePath + _AssetBundleMainName);
//依赖包加载
_AssetBundleManifest = _AssetBundleMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
}
//从固定文件中得到依赖信息
//得到你想要知道 当前AB包集中的所有依赖
string[] _DependStr = _AssetBundleManifest.GetAllDependencies(_AssetBundleName);
//如果有依赖包的话
if (_DependStr.Length > 0)
{
//资源 AB 包
AssetBundle _NewAssetBundleSubset;
for (int i = 0; i < _DependStr.Length; i++)
{
//判断 AB 包是否加载过
//如果没有加载过
if (!_AssetBundleDic.ContainsKey(_DependStr[i]))
{
//依赖包加载
_NewAssetBundleSubset = AssetBundle.LoadFromFile(_AssetBundlePath + _DependStr[i]);
//AB包 字典数据存储
_AssetBundleDic.Add(_DependStr[i], _NewAssetBundleSubset);
}
}
//判断 AB 包是否加载过
//如果没有加载过
if (!_AssetBundleDic.ContainsKey(_AssetBundleName))
{
//使用资源 AB 包加载 并进行重新赋值
_NewAssetBundleSubset = AssetBundle.LoadFromFile(_AssetBundlePath + _AssetBundleName);
//AB包 字典数据存储
_AssetBundleDic.Add(_AssetBundleName, _NewAssetBundleSubset);
}
}
}
/// <summary>
/// 单个 AssetBundle 包 卸载
/// </summary>
/// <param name="_AssetBundleName"></param>
public void UnLoadAssetBuindle(string _AssetBundleName)
{
//判断当前 AB包数据 字典是否存在 当前AB 包资源
if (_AssetBundleDic.ContainsKey(_AssetBundleName))
{
//AB 包集卸载
//false 只卸载AB 包集 但是不卸载资源
//true 卸载AB 包集 同时也卸载资源
//避免重复加载报空
_AssetBundleDic[_AssetBundleName].Unload(false);
//移除 AB数据字典
_AssetBundleDic.Remove(_AssetBundleName);
}
}
/// <summary>
/// 所有 AssetBundle 包 卸载
/// </summary>
/// <param name="_AssetBundleName"></param>
public void UnLoadAllAssetBuindles()
{
//卸载所有当前加载的资源包
//false 只卸载AB 包集 但是不卸载资源
//true 卸载AB 包集 同时也卸载资源
//避免重复加载报空
AssetBundle.UnloadAllAssetBundles(false);
//AB数据字典 清空
_AssetBundleDic.Clear();
//AssetBundle 主包
_AssetBundleMain = null;
//依赖包配置文件
_AssetBundleManifest = null;
//AssetBundle主包 加载路径
_AssetBundlePath = null;
//主包名
_AssetBundleMainName = null;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
//同步加载 不指定类型加载
LoadAssetBundleSync("model", "CubeModle");
//同步加载 指定类型加载
LoadAssetBundleSync("model", "SphereModel",typeof(GameObject));
//同步加载 不指定类型 泛型加载
LoadAssetBundleSync<GameObject>("model", "CylinderModle");
}
if (Input.GetKeyDown(KeyCode.E))
{
//同步加载 不指定类型加载
LoadResAsync("model", "CubeModle",(_Obj=>
{
(_Obj as GameObject).transform.position = new Vector3((_Obj as GameObject).transform.position.x, 3, (_Obj as GameObject).transform.position.z);
}));
//同步加载 指定类型加载
//同步加载 不指定类型加载
LoadResAsync("model", "SphereModel",typeof(GameObject), (_Obj =>
{
(_Obj as GameObject).transform.position = new Vector3((_Obj as GameObject).transform.position.x, 3, (_Obj as GameObject).transform.position.z);
}));
//同步加载 不指定类型 泛型加载
//同步加载 不指定类型加载
LoadResAsync<GameObject>("model", "CylinderModle", (_Obj =>
{
_Obj .transform.position = new Vector3(_Obj.transform.position.x, 3, _Obj.transform.position.z);
}));
}
}
}
搭载运行
脚本搭载
基础运行
点击两次也不会报错说明运行良好可以直接使用
暂时先这样吧,如果有时间的话就会更新,实在看不明白就留言,看到我会回复的。
路漫漫其修远兮,与君共勉。