找回密码
 立即注册
查看: 253|回复: 0

Unity 实现AssetBundle动态加载预制体

[复制链接]
发表于 2022-4-22 08:24 | 显示全部楼层 |阅读模式
1.AssetBundle类

首先在Assets目录下新建一个 Editor文件夹,把我们创建AssetBundle的脚本放在Editor里面,脚本名字就命名为AssetBundle。然后再创建一个命名为StreamingAssets的文件夹存放打包的文件,当然还需要有动态加载的预制体,选中需要AssetBundle动态加载的预制体,然后新建一个AssetBundle标记如下图所示


  然后编写代码
[MenuItem("AssetBundle/BuildWebGL")]
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("TaskManager");
                        singleton = go.AddComponent<TaskManager>();
                }
                return new TaskState(coroutine);
        }
}  现在生成加载的代码我们都完成了,现在我们需要在需要动态加载的地方开始加载他们,例如我们在启动编辑器的时候就加载,那么我们就把加载写在Start函数里面就可以了:代码如下:
void Start()
{
    AssetsBundleMgr.DowloadAsset(Application.dataPath + "/StreamingAssets/", "cube", (go) =>
    {
        var scene = go as GameObject;
        //这里可以初始化该物体的各种属性
    });
}到这里就全部结束了。如果有觉得哪里有问题的地方欢迎指出,谢谢!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-16 20:35 , Processed in 0.093194 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表