📜  如何统一更改场景 - C# (1)

📅  最后修改于: 2023-12-03 14:53:14.783000             🧑  作者: Mango

如何统一更改场景 - C#

在现代游戏开发中,场景切换是一个经常出现的任务。为了使游戏更加流畅,我们通常会使用异步加载和卸载场景。然而,如果不小心管理,场景切换可能会导致各种问题和错误。为了解决这些问题,我们可以使用一些技巧和最佳实践来统一管理这个过程。

使用场景管理器

Unity 引擎提供了一个内置的 SceneManagement Namespace,其中包含了用于管理场景的各个组件。使用 SceneManager 组件,可以方便地加载/卸载场景、获取场景信息以及跳转场景等操作。

加载场景

要加载场景,可以使用以下代码:

SceneManager.LoadScene("SceneName", LoadSceneMode.Additive);

其中 SceneName 是场景文件的名称, LoadSceneMode.Additive 表示新场景将添加到现有场景中。如果想要替换现有场景,请使用 LoadSceneMode.Single

卸载场景

要卸载场景,可以使用以下代码:

SceneManager.UnloadScene("SceneName");
获取当前场景

要获取当前场景的名称,可以使用以下代码:

string currentSceneName = SceneManager.GetActiveScene().name;
判断场景是否加载完成

在异步加载场景时,我们通常需要知道场景是否已经加载完成,以便在继续执行之前等待场景加载完成。可以使用以下代码来实现:

IEnumerator LoadSceneAsync()
{
    AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("SceneName", LoadSceneMode.Additive);
    while (!asyncLoad.isDone)
    {
        yield return null;
    }
    // 场景已经加载完成
}
统一管理场景切换

使用 SceneManager 组件后,我们可以开始编写自己的场景管理器。场景管理器的作用是跟踪当前场景、处理场景切换和异步加载等操作。

以下是一个简单的场景管理器实现:

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

public class SceneManager : MonoBehaviour
{
    public string InitialSceneName; //第一个场景的名称
    private Dictionary<string, bool> _sceneState = new Dictionary<string, bool>();

    private static SceneManager _instance;
    public static SceneManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<SceneManager>();
            }
            return _instance;
        }
    }

    void Awake()
    {
        if (Instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
            return;
        }

        LoadScene(InitialSceneName, true);
    }

    public void LoadScene(string level, bool async = false)
    {
        if (_sceneState.ContainsKey(level) && _sceneState[level] == true)
        {
            Debug.LogWarning("Scene already loaded: " + level);
            return;
        }

        if (async)
        {
            StartCoroutine(LoadSceneAsync(level));
        }
        else
        {
            SceneManager.LoadScene(level);
            _sceneState[level] = true;
        }
    }

    private IEnumerator LoadSceneAsync(string level)
    {
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(level, LoadSceneMode.Additive);

        while (!asyncLoad.isDone)
        {
            yield return null;
        }

        _sceneState[level] = true;
    }
}

我们可以在 Unity Editor 中将 SceneManager 组件添加到一个 GameObject 上,并设置 InitialSceneName 的值为想要加载的第一个场景的名称。在场景中,可以使用 SceneManager.Instance.LoadScene("SceneName", true); 来异步加载新场景。

参考