UnityでのSceneを遷移は
SceneManager.LoadSceneAsync(sceneName);
のように行いますが、初めに各種マネージャーなどメインsceneを作っておき、
SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
のようにシーンを追加するように管理するのが一般的です。
ここで、sceneName
という文字列ではなく、Inspectorにsceneそのものを選択できるようにしてみます。
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に追加しておく必要があります。
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になってしまうので注意が必要です。