0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Scene遷移 / gameObjectが属しているSceneを得る

Last updated at Posted at 2024-07-13

UnityでのSceneを遷移は
SceneManager.LoadSceneAsync(sceneName);
のように行いますが、初めに各種マネージャーなどメインsceneを作っておき、
SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
のようにシーンを追加するように管理するのが一般的です。
image.png

ここで、sceneNameという文字列ではなく、Inspectorにsceneそのものを選択できるようにしてみます。
image.png

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

namespace TmLib
{
    public class ExSceneManager : MonoBehaviour
    {
        public static ExSceneManager Instance { get; private set; }
        public string[] sceneNames { get; private set; }
#if UNITY_EDITOR
        [SerializeField] UnityEditor.SceneAsset[] sceneAssets;
#endif

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

#if UNITY_EDITOR
        private void OnValidate()
        {
            if (sceneAssets != null)
            {
                sceneNames = new string[sceneAssets.Length];
                for (int i = 0; i < sceneAssets.Length; i++)
                {
                    if (sceneAssets[i] != null)
                    {
                        sceneNames[i] = sceneAssets[i].name;
                    }
                }
            }
        }
#endif
    }
}

SceneManagerと名前がついていますが、単にsceneをリストに積めるようにしただけのものです。
sceneAssetsの値が変化するとOnValodate()が呼ばれるので、この中でsceneの文字列リストを生成しています。

実際にこのリストを使用してシーン遷移をするサンプルが以下になります。

実行するには,あらかじめ各シーンをScene Listに追加しておく必要があります。

image.png

SceneCtrl.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using TmLib;

namespace QiitaTest
{
    public class SceneCtrl : MonoBehaviour
    {
        [SerializeField] List<string> m_addedSceneNamesList = new List<string>();

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

        // Update is called once per frame
        void Update()
        {
        }

        public bool PushScene(int _sceneId)
        {
            bool ret = false;
            if (ExSceneManager.Instance.sceneNames.Length > _sceneId)
            {
                string sceneName = ExSceneManager.Instance.sceneNames[_sceneId];
                m_addedSceneNamesList.Add(sceneName);
                SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
                ret = true;
            }
            return ret;
        }

        public bool PopScene()
        {
            bool ret = false;
            if (ExSceneManager.Instance.sceneNames.Length > 0)
            {
                string sceneName = m_addedSceneNamesList[m_addedSceneNamesList.Count - 1];
                m_addedSceneNamesList.RemoveAt(m_addedSceneNamesList.Count - 1);
                SceneManager.UnloadSceneAsync(sceneName);
                ret = true;
            }
            return ret;
        }

        public int ClearScene()
        {
            int ret = 0;
            foreach (string sceneName in m_addedSceneNamesList)
            {
                SceneManager.UnloadSceneAsync(sceneName);
                ret++;
            }   
            m_addedSceneNamesList.Clear();
            return ret;
        }

        /// <summary>
        /// 最後にpushしたシーンをunloadして、指定したシーンをloadする
        /// </summary>
        /// <param name="_sceneId"></param>
        public void SwapScene(int _sceneId)
        {
            PopScene();
            PushScene(_sceneId);
        }

        IEnumerator loadTestCo()
        {
            yield return new WaitForSeconds(1.0f);
            PushScene(0); // scene0をロード
            yield return new WaitForSeconds(1.0f);
            SwapScene(1); // scene0を消してscene1をロード
            yield return new WaitForSeconds(1.0f);
            SwapScene(2); // scene1を消してscene2をロード
            yield return new WaitForSeconds(1.0f);
            PushScene(0); // scene0を追加ロード
            yield return new WaitForSeconds(1.0f);
            PushScene(1); // scene1を追加ロード
            yield return new WaitForSeconds(1.0f);
            ClearScene(); // 追加したsceneをすべて削除
            yield return new WaitForSeconds(1.0f);
            PushScene(0); // scene0を追加ロード
            PushScene(1); // scene1を追加ロード
            PushScene(2); // scene2を追加ロード
        }
    }
}

また、各gameObjectが度のシーンに属しているかは、
gameObject.scene.nameで知ることができます。
ただし、DontDestroyOnLoad()してしまうと
シーン名もDontDestroyOnLoadになってしまうので注意が必要です。
image.png
image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?