Unity 工具类 之 简单的异步场景加载(包含加载进度和同步加载方法)类 LoadSceneManager 实现

Unity 工具类 之 简单的异步场景加载(包含加载进度和同步加载方法)类 LoadSceneManager 实现

 

目录

Unity 工具类 之 简单的异步场景加载(包含加载进度和同步加载方法)类 LoadSceneManager 实现

 一、简单介绍

 二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键代码

七、参考工程


 

 

 
一、简单介绍

Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。

简单的异步场景加载(包含加载进度和同步加载方法)类,单独做了一个单例类,提供加载场景方法和加载进度,供外界调用即可。

 
二、实现原理

1、单例类,保证整个场景中只有一个类管理场景加载;

2、LoadSceneManager.Instance.LoadSceneAsync  即可异步加载场景;

3、LoadSceneManager.Instance.LoadScene  即可同步加载场景;

4、LoadSceneManager.Instance.ProgressLoadSceneAsync 即可获取异步加载进度;

 

三、注意事项

1、枚举管理场景名称;

2、获取进度,根据实际情况进行转化,进度值范围为 0 ~ 100 之间;

 

四、效果预览

 

五、实现步骤

1、打开Unity,新建一个工程,新建一个 Start 场景,场景中布局一些场景加载进度的 UI,如下图

 

2、新建一个 Game 场景,布局添加一个 UI ,提示场景即可,如下图

 

3、新建脚本,单例类,场景加载管理类,和一个测试场景加载的类,如下图

 

4、把 测试类脚本挂载到 Start 场景中,并对应赋值,如下图

 

5、把场景添加到 Build Settings 中,如下图

 

6、运行场景,效果如下

 

六、关键代码

1、TestScript

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TestScript : MonoBehaviour
{
    public Slider progressSlider;
    public Text progressText;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)) {
            Debug.Log("GetKeyDown(KeyCode.Space)");

            LoadSceneAsync();
        }
    }

    void LoadSceneAsync() {

        progressSlider.value = 0;
        progressText.text = "进度";

        LoadSceneManager.Instance.LoadSceneAsync(ScenesName.Game, ShowProgress, ()=> { Debug.Log("开始异步加载场景..."); }, () => { Debug.Log("开始异步加载完成,跳转场景"); } );
    }

    void ShowProgress(float progress) {
        Debug.Log("progress:" + progress);
        progressSlider.value = progress / 100;
        progressText.text = "进度: " + progress +" %";
    }
}

 

2、LoadSceneManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

/// <summary>
/// 场景枚举
/// </summary>
public enum ScenesName {
    Start,
    Game,
}

public class LoadSceneManager : MonoSingleton<LoadSceneManager>
{
    //异步加载对象
    private AsyncOperation prog;    

    // 异步加载进度参数
    int toProgress = 0;
    int showProgress = 0;

    // 异步加载事件
    System.Action<float> loadingAction = null;
    System.Action loadBeforeAction = null;
    System.Action loadedEndAction = null;

    /// <summary>
    /// 同步加载场景
    /// </summary>
    /// <param name="scenesName">场景名称</param>
    public void LoadScene(ScenesName scenesName) {

        SceneManager.LoadScene(scenesName.ToString());
    }

    /// <summary>
    /// 异步加载
    /// </summary>
    /// <param name="scenesName">场景名称</param>
    /// <param name="loadingAction">加载中的事件</param>
    /// <param name="loadBeforeAction">异步加载前的事件</param>
    /// <param name="loadedEndAction">异步加载完成后的事件</param>
    public void LoadSceneAsync(ScenesName scenesName, System.Action<float> loadingAction = null, System.Action loadBeforeAction = null, System.Action loadedEndAction = null) {
        // 事件赋值
        this.loadBeforeAction = loadBeforeAction;
        this.loadingAction = loadingAction;
        this.loadedEndAction = loadedEndAction;

        StartCoroutine(LoadingScene(scenesName));
    }

    /// <summary>
    /// 异步加载进度
    /// </summary>
    /// <returns></returns>
    public float ProgressLoadSceneAsync() { 

        return showProgress;
    }

    /// <summary>
    /// 协程加载场景
    /// </summary>
    /// <param name="scenesName">场景名称</param>
    /// <param name="loadingAction">加载中的事件</param>
    /// <param name="loadBeforeAction">异步加载前的事件</param>
    /// <param name="loadedEndAction">异步加载完成后的事件</param>
    /// <returns></returns>
    private IEnumerator LoadingScene(ScenesName scenesName)
    {
        // 异步加载前的事件
        if (this.loadBeforeAction != null) {
            this.loadBeforeAction.Invoke();
        }

        prog = SceneManager.LoadSceneAsync(scenesName.ToString());  //异步加载场景

        prog.allowSceneActivation = false;  //如果加载完成,也不进入场景

        toProgress = 0;
        showProgress = 0;

        //测试了一下,进度最大就是0.9
        while (prog.progress < 0.9f)
        {
            toProgress = (int)(prog.progress * 100);

            while (showProgress < toProgress)
            {
                showProgress++;

                // 异步加载中的事件
                if (this.loadingAction != null)
                {
                    this.loadingAction.Invoke(showProgress);
                }
            }
            yield return new WaitForEndOfFrame(); //等待一帧
        }
        //计算0.9---1   其实0.9就是加载好了,我估计真正进入到场景是1  
        toProgress = 100;

        while (showProgress < toProgress)
        {
            showProgress++;

            // 异步加载中的事件
            if (this.loadingAction != null)
            {
                this.loadingAction.Invoke(showProgress);
            }

            yield return new WaitForEndOfFrame(); //等待一帧
        }

        // 异步加载完成后的事件
        if (this.loadedEndAction != null)
        {
            this.loadedEndAction.Invoke();
        }

        yield return new WaitForEndOfFrame(); //等待一帧


        prog.allowSceneActivation = true;  //如果加载完成,进入场景
    }

   
}


 

3、MonoSingleton

using UnityEngine;

public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T instance = null;

    private static readonly object locker = new object();

    private static bool bAppQuitting;

    public static T Instance
    {
        get
        {
            if (bAppQuitting)
            {
                instance = null;
                return instance;
            }

            lock (locker)
            {
                if (instance == null)
                {
                    instance = FindObjectOfType<T>();
                    if (FindObjectsOfType<T>().Length > 1)
                    {
                        Debug.LogError("不应该存在多个单例!");
                        return instance;
                    }

                    if (instance == null)
                    {
                        var singleton = new GameObject();
                        instance = singleton.AddComponent<T>();
                        singleton.name = "(singleton)" + typeof(T);
                        singleton.hideFlags = HideFlags.None;
                        DontDestroyOnLoad(singleton);
                    }
                    else
                        DontDestroyOnLoad(instance.gameObject);
                }
                instance.hideFlags = HideFlags.None;
                return instance;
            }
        }
    }

    private void Awake()
    {
        bAppQuitting = false;
    }

    private void OnDestroy()
    {
        bAppQuitting = true;
    }
}

 

 

七、参考工程

点击即可下载

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仙魁XAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值