유니티 Scene Change할 때 자주 사용돼서 만들어두는 Util Class

Scene Wrapper 예시 코드

using UnityEngine;
using UnityEngine.SceneManagement;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif

public static class SceneWrapper
{
    private static Action beforeSceneLoadCallback;
    private static Action afterSceneLoadCallback;

    public static void ChangeScene(string sceneName, LoadSceneMode mode = LoadSceneMode.Single,
        Action beforeLoad = null,
        Action afterLoad = null)
    {
        beforeSceneLoadCallback = beforeLoad;
        afterSceneLoadCallback = afterLoad;

        beforeSceneLoadCallback?.Invoke();

        SceneManager.sceneLoaded += OnSceneLoaded;
        SceneManager.LoadSceneAsync(sceneName, mode);
    }

    public static void ChangeScene(int sceneIndex, LoadSceneMode mode = LoadSceneMode.Single,
        Action beforeLoad = null,
        Action afterLoad = null)
    {
        beforeSceneLoadCallback = beforeLoad;
        afterSceneLoadCallback = afterLoad;

        beforeSceneLoadCallback?.Invoke();

        SceneManager.sceneLoaded += OnSceneLoaded;
        SceneManager.LoadSceneAsync(sceneIndex, mode);
    }

    private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        afterSceneLoadCallback?.Invoke();

        SceneManager.sceneLoaded -= OnSceneLoaded;
        afterSceneLoadCallback = null;
        beforeSceneLoadCallback = null;
    }

    public static Scene GetActiveScene()
    {
        return SceneManager.GetActiveScene();
    }

    public static bool IsSceneLoaded(string sceneName)
    {
        for (int i = 0; i < SceneManager.sceneCount; i++)
        {
            if (SceneManager.GetSceneAt(i).name == sceneName)
                return true;
        }
        return false;
    }

    public static void ReloadCurrentScene(Action beforeLoad = null, Action afterLoad = null)
    {
        var currentScene = SceneManager.GetActiveScene();
        ChangeScene(currentScene.name, LoadSceneMode.Single, beforeLoad, afterLoad);
    }

    public static void UnloadScene(string sceneName, Action callback = null)
    {
        SceneManager.sceneUnloaded += OnSceneUnloaded;

        void OnSceneUnloaded(Scene scene)
        {
            if (scene.name == sceneName)
            {
                callback?.Invoke();
                SceneManager.sceneUnloaded -= OnSceneUnloaded;
            }
        }

        SceneManager.UnloadSceneAsync(sceneName);
    }

#if UNITY_EDITOR
    public static class SceneUtils
    {
        public static int GetSceneIndex(SceneAsset scene)
        {
            for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
            {
                string scenePath = SceneUtility.GetScenePathByBuildIndex(i);
                string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
                if (sceneName == scene.name)
                {
                    return i;
                }
            }
            return -1;
        }

        public static string GetSceneNameByIndex(int index)
        {
            if (index < 0 || index >= SceneManager.sceneCountInBuildSettings)
                return null;

            string scenePath = SceneUtility.GetScenePathByBuildIndex(index);
            return System.IO.Path.GetFileNameWithoutExtension(scenePath);
        }

        public static SceneAsset GetSceneAssetByIndex(int index)
        {
            string scenePath = SceneUtility.GetScenePathByBuildIndex(index);
            return AssetDatabase.LoadAssetAtPath<SceneAsset>(scenePath);
        }
    }
#endif
}

 


사용예제

using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneChanger : MonoBehaviour
{
    [SerializeField] private int nextSceneIndex;
    [SerializeField] private int previousSceneIndex;

#if UNITY_EDITOR
    [SerializeField] private UnityEditor.SceneAsset nextScene;
    [SerializeField] private UnityEditor.SceneAsset previousScene;

    private void OnValidate()
    {
        nextSceneIndex = GetSceneIndex(nextScene);
        previousSceneIndex = GetSceneIndex(previousScene);
    }

    private int GetSceneIndex(UnityEditor.SceneAsset scene)
    {
        return scene != null ? SceneWrapper.SceneUtils.GetSceneIndex(scene) : -1;
    }
#endif

    public void LoadNextScene()
    {
        LoadSceneByIndex(nextSceneIndex, "Next Scene");
    }

    public void LoadPreviousScene()
    {
        LoadSceneByIndex(previousSceneIndex, "Previous Scene");
    }

    public void ReloadCurrentScene()
    {
        int currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
        LoadSceneByIndex(currentSceneIndex, "Current Scene");
    }

    protected virtual void BeforeSceneLoad() { }

    protected virtual void AfterSceneLoad() { }

    private void LoadSceneByIndex(int sceneIndex, string sceneDescription)
    {
        if (sceneIndex < 0)
        {
            Debug.LogWarning($"{sceneDescription} index is invalid.");
            return;
        }

        SceneWrapper.ChangeScene(sceneIndex,
            beforeLoad: BeforeSceneLoad,
            afterLoad: AfterSceneLoad);
    }
}

 

using UnityEngine;

public class MainGameSceneChanger : SceneChanger
{
    protected override void BeforeSceneLoad()
    {
        Debug.Log("Saving game data before loading Main Game Scene...");
        // (예시) 게임 데이터 저장 로직
    }

    protected override void AfterSceneLoad()
    {
        Debug.Log("Initializing player stats for Main Game Scene...");
        // (예시) 플레이어 상태 초기화 로직
    }
}