Simple asynchronous scene loading (including loading progress and synchronous loading method) of Unity tool class LoadSceneManager implementation

 

Catalog

Simple asynchronous scene loading (including loading progress and synchronous loading method) of Unity tool class LoadSceneManager implementation

I. brief introduction

II. Implementation principle

3, Precautions

4, Effect preview

5, Implementation steps

6, Key code

7, Reference Engineering

 

 

 
1, Brief introduction

Unity tool class, some modules that may be used in game development sorted out by ourselves, can be used independently to facilitate game development.

A simple asynchronous scene loading (including loading progress and synchronous loading method) class, with a single instance class, provides loading scene method and loading progress for external calls.

 
2, Implementation principle

1. A single instance class ensures that only one class in the whole scenario manages localized multilingual data;

2. LoadSceneManager.Instance.LoadSceneAsync can load scenarios asynchronously;

3. LoadSceneManager.Instance.LoadScene to load the scene synchronously;

4. LoadSceneManager.Instance.ProgressLoadSceneAsync to get the asynchronous loading progress;

 

3, Precautions

1. Enumerate management scenario names;

2. Obtain the progress, convert according to the actual situation, and the progress value range is 0 ~ 100;

 

4, Effect preview

 

5, Implementation steps

1. Open Unity, create a new project, create a new Start scenario, and layout the UI of loading progress of some scenarios in the scenario, as shown in the following figure

 

2. Create a new Game scene, add a UI to the layout, and prompt the scene, as shown in the following figure

 

3. Create a new script, singleton class, scenario loading management class, and a test scenario loading class, as shown in the following figure

 

4. Mount the test class script to the Start scenario, and assign values accordingly, as shown in the following figure

 

5. Add the scene to Build Settings, as shown below

 

6. Running scenario, the effect is as follows

 

6, Key code

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 = "Speed of progress";

        LoadSceneManager.Instance.LoadSceneAsync(ScenesName.Game, ShowProgress, ()=> { Debug.Log("Start asynchronous loading scenario..."); }, () => { Debug.Log("Start to load asynchronously and finish, jump to the scene"); } );
    }

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

 

2,LoadSceneManager

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

/// <summary>
///Scene enumeration
/// </summary>
public enum ScenesName {
    Start,
    Game,
}

public class LoadSceneManager : MonoSingleton<LoadSceneManager>
{
    //Load objects asynchronously
    private AsyncOperation prog;    

    // Asynchronous load progress parameters
    int toProgress = 0;
    int showProgress = 0;

    // Asynchronous load event
    System.Action<float> loadingAction = null;
    System.Action loadBeforeAction = null;
    System.Action loadedEndAction = null;

    /// <summary>
    ///Load scene synchronously
    /// </summary>
    ///< param name = "scenesname" > scene name < / param >
    public void LoadScene(ScenesName scenesName) {

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

    /// <summary>
    ///Asynchronous load
    /// </summary>
    ///< param name = "scenesname" > scene name < / param >
    ///Event in loading < / param >
    ///Events before asynchronous loading < / param >
    ///Event after asynchronous loading < / param >
    public void LoadSceneAsync(ScenesName scenesName, System.Action<float> loadingAction, System.Action loadBeforeAction = null, System.Action loadedEndAction = null) {
        // Event Assignment
        this.loadBeforeAction = loadBeforeAction;
        this.loadingAction = loadingAction;
        this.loadedEndAction = loadedEndAction;

        StartCoroutine(LoadingScene(scenesName));
    }

    /// <summary>
    ///Asynchronous load progress
    /// </summary>
    /// <returns></returns>
    public float ProgressLoadSceneAsync() { 

        return showProgress;
    }

    /// <summary>
    ///Scenario of CO process loading
    /// </summary>
    ///< param name = "scenesname" > scene name < / param >
    ///Event in loading < / param >
    ///Events before asynchronous loading < / param >
    ///Event after asynchronous loading < / param >
    /// <returns></returns>
    private IEnumerator LoadingScene(ScenesName scenesName)
    {
        // Events before asynchronous load
        if (this.loadBeforeAction != null) {
            this.loadBeforeAction.Invoke();
        }

        prog = SceneManager.LoadSceneAsync(scenesName.ToString());  //Asynchronous loading scenario

        prog.allowSceneActivation = false;  //If the loading is completed, you will not enter the scene

        toProgress = 0;
        showProgress = 0;

        //After testing, the maximum progress is 0.9
        while (prog.progress < 0.9f)
        {
            toProgress = (int)(prog.progress * 100);

            while (showProgress < toProgress)
            {
                showProgress++;

                // Events in asynchronous load
                if (this.loadingAction != null)
                {
                    this.loadingAction.Invoke(showProgress);
                }
            }
            yield return new WaitForEndOfFrame(); //Wait for a frame.
        }
        //The calculation of 0.9-1 is actually 0.9, which is loaded. I guess the real entry into the scene is 1  
        toProgress = 100;

        while (showProgress < toProgress)
        {
            showProgress++;

            // Events in asynchronous load
            if (this.loadingAction != null)
            {
                this.loadingAction.Invoke(showProgress);
            }

            yield return new WaitForEndOfFrame(); //Wait for a frame.
        }

        // Events after asynchronous loading
        if (this.loadedEndAction != null)
        {
            this.loadedEndAction.Invoke();
        }

        yield return new WaitForEndOfFrame(); //Wait for a frame.


        prog.allowSceneActivation = true;  //If loading is complete, enter the scene
    }

   
}


 

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("There should not be multiple singletons!");
                        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;
    }
}

 

 

7, Reference Engineering

Click to download

Published 79 original articles, won praise 24, and received 90 thousand visits+
Private letter follow

Tags: Unity

Posted on Sun, 12 Jan 2020 05:44:26 -0800 by mispris006