Unity 实现AssetBundle动态加载预制体
1.AssetBundle类首先在Assets目录下新建一个 Editor文件夹,把我们创建AssetBundle的脚本放在Editor里面,脚本名字就命名为AssetBundle。然后再创建一个命名为StreamingAssets的文件夹存放打包的文件,当然还需要有动态加载的预制体,选中需要AssetBundle动态加载的预制体,然后新建一个AssetBundle标记如下图所示
然后编写代码
private static void BundleAssetsBundle_Webgl()
{
BuildAssetsBundle(BuildTarget.WebGL);
}
private static void BuildAssetsBundle(BuildTarget target)
{
string packagePath = Application.streamingAssetsPath;
if (packagePath.Length <= 0 && !Directory.Exists(packagePath))
{
return;
}
BuildPipeline.BuildAssetBundles(packagePath, BuildAssetBundleOptions.UncompressedAssetBundle, target);
}
这边BuildTarget我就以WebGl为例子了,路径为本地路径,这边就已经写好创建AssetBundle,下面我们要开始动态加载AssetBundle包。
2.AssetBundleMgr类
当我们把前面所需的都打包好了,现在我们要开始加载AssetBundle包了,然后开始编写代码
public static void DowloadAsset(string url, string name, Action<object> callback)
{
new Task(GetAssetbundle(url, name, callback));//这边需要自己在写一个Task类
}
private static IEnumerator GetAssetbundle(string url, string name, Action<object> callback)
{
var uwr = UnityWebRequestAssetBundle.GetAssetBundle(url + name);//获取动态加载路径
yield return uwr.SendWebRequest(); //等待发送web请求
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);//下载AssetBundle包
var loadAsset = bundle.LoadAssetAsync<GameObject>(name);//加载类型
yield return loadAsset; //等待完成
var prefab = loadAsset.asset;
var go = GameObject.Instantiate(prefab); //克隆需要加载的包
callback(go);
bundle.Unload(false);
Resources.UnloadUnusedAssets();//加载了包就要卸载
}3.Task类和TaskManager类
这个类可以在GitHub上直接复制过来,直接用就可以了
public class Task
{
/// Returns true if and only if the coroutine is running.Paused tasks
/// are considered to be running.
public bool Running
{
get
{
return task.Running;
}
}
/// Returns true if and only if the coroutine is currently paused.
public bool Paused
{
get
{
return task.Paused;
}
}
/// Delegate for termination subscribers.manual is true if and only if
/// the coroutine was stopped with an explicit call to Stop().
public delegate void FinishedHandler(bool manual);
/// Termination event.Triggered when the coroutine completes execution.
public event FinishedHandler Finished;
/// Creates a new Task object for the given coroutine.
///
/// If autoStart is true (default) the task is automatically started
/// upon construction.
public Task(IEnumerator c, bool autoStart = true)
{
task = TaskManager.CreateTask(c);
task.Finished += TaskFinished;
if (autoStart)
Start();
}
/// Begins execution of the coroutine
public void Start()
{
task.Start();
}
/// Discontinues execution of the coroutine at its next yield.
public void Stop()
{
task.Stop();
}
public void Pause()
{
task.Pause();
}
public void Unpause()
{
task.Unpause();
}
void TaskFinished(bool manual)
{
FinishedHandler handler = Finished;
if (handler != null)
handler(manual);
}
TaskManager.TaskState task;
}
class TaskManager : MonoBehaviour
{
public class TaskState
{
public bool Running
{
get
{
return running;
}
}
public bool Paused
{
get
{
return paused;
}
}
public delegate void FinishedHandler(bool manual);
public event FinishedHandler Finished;
IEnumerator coroutine;
bool running;
bool paused;
bool stopped;
public TaskState(IEnumerator c)
{
coroutine = c;
}
public void Pause()
{
paused = true;
}
public void Unpause()
{
paused = false;
}
public void Start()
{
running = true;
singleton.StartCoroutine(CallWrapper());
}
public void Stop()
{
stopped = true;
running = false;
}
IEnumerator CallWrapper()
{
yield return null;
IEnumerator e = coroutine;
while (running)
{
if (paused)
yield return null;
else
{
if (e != null && e.MoveNext())
{
yield return e.Current;
}
else
{
running = false;
}
}
}
FinishedHandler handler = Finished;
if (handler != null)
handler(stopped);
}
}
static TaskManager singleton;
public static TaskState CreateTask(IEnumerator coroutine)
{
if (singleton == null)
{
GameObject go = new GameObject(&#34;TaskManager&#34;);
singleton = go.AddComponent<TaskManager>();
}
return new TaskState(coroutine);
}
}现在生成加载的代码我们都完成了,现在我们需要在需要动态加载的地方开始加载他们,例如我们在启动编辑器的时候就加载,那么我们就把加载写在Start函数里面就可以了:代码如下:
void Start()
{
AssetsBundleMgr.DowloadAsset(Application.dataPath + &#34;/StreamingAssets/&#34;, &#34;cube&#34;, (go) =>
{
var scene = go as GameObject;
//这里可以初始化该物体的各种属性
});
}到这里就全部结束了。如果有觉得哪里有问题的地方欢迎指出,谢谢!
页:
[1]