Edited at

[Unity] Sceneの役割や使い方をざっくりまとめた

More than 3 years have passed since last update.

Unity触る上で避けては通れないのでざっくり書いた


Sceneとは?


SceneをUnityEditor上で作る


  • Pojectビュー上の[create]ボタン (もしくは右クリック > Create) からSceneを選択

  • もしくは上部メニューより [Edit] => [NewScene] を選択で新規Sceneが読み込まれる



    • [Ctrl(Cmd) + n] がショートカット




SceneをUnityEditor上で読み込む


  • Project上での任意のSceneファイルをダブルクリック


    • 現在Hierarchy上で開かれているSceneは閉じられる(アンロードされる)ので注意

    • 複数のSceneを読み込んでいる場合、全て閉じられるので注意



  • 複数のSceneを同時に読み込みたい場合は任意のSceneファイルをHierarchy上にドラッグ&ドロップ

addscene.gif

(実際はCameraを破棄されないGameObjectとして複数混在させないほうが良いがDEMO用に...)


SceneをUnityEditor上でアンロードする


  • https://docs.unity3d.com/ja/current/Manual/MultiSceneEditing.html

  • Hierarchy上の任意のシーンを右クリック (もしくはScene名右のメニューを展開)


  • UnloadScene


    • シーンをアンロードされるが、Hierarchy内に表示されたままとなる

    • Editor上で一時的に特定のシーンを無効にしたいときに使用する




  • RemoveScene


    • シーンをアンロードし、Hierarchy上からも消す



unloadscene.gif


Sceneの保存形式をバイナリからテキストに変更する


  • デフォルトではバイナリファイルで保存される

  • この状態でgit等でバージョン管理した際にコンフリクトすると解消が困難


    • (テキストに切り替えても仕様ベースの問題で解消困難なケースは多々あるけど....)



  • 設定からテキスト(YAML形式)として保存するようにしておくことをオススメ


変更方法



  • [Edit] => [Project Settings] => [Editor] でEditorSettingsを表示


  • AssetSerializationForceText に変更

forcetext.png


BuildSettingsにSceneを定義する


  • https://docs.unity3d.com/jp/current/Manual/BuildSettings.html

  • 上部メニューより [File] => [BuildSettings...] を開く

  • 上部の Scenes in Build にSceneを登録しないと実行時に動的に呼び出せないので注意


    • SceneをEditor上で開いた状態で [Add Open Scenes] を選択する

    • Project上のSceneファイルをドラッグ&ドロップする



buildsetting.gif


実行中にScript上からSceneを操作する


SceneManagerについて

using UnityEngine.SceneManagement;


任意のSceneに切り替える

using UnityEngine;

using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{
public void MoveScene()
{
// 引数にシーン名を指定する
// Build Settings で確認できる sceneBuildIndex を指定しても良い
SceneManager.LoadScene("stage1");
}
}


任意のSceneを追加で読み込む

using UnityEngine;

using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{
public void AddScene()
{
SceneManager.LoadScene("stage2", LoadSceneMode.Additive);
}
}


任意のSceneを非同期に読み込む

using UnityEngine;

using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{
public void AddSceneAsync()
{
SceneManager.LoadSceneAsync("stage3", LoadSceneMode.Additive);
}
}


任意のSceneをアンロードする

using UnityEngine;

using UnityEngine.SceneManagement;

public class SceneTest : MonoBehaviour
{
public void RemoveScene()
{
// 引数にシーン名を指定する
// Build Settings で確認できる sceneBuildIndex を指定しても良い
SceneManager.UnloadScene("stage1");
}
}


現在読み込まれているSceneの名称をリストで取得する

using UnityEngine.SceneManagement;

using System.Collections.Generic;

public static class SceneUtil
{
public static List<string> GetActiveSceneNames()
{
int sceneCount = SceneManager.sceneCount;
List<string> activeSceneNames = new List<string>();
for (int i = 0; i < sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
activeSceneNames.Add(scene.name);
}
return activeSceneNames;
}
}

using UnityEngine;

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

public class SceneTest : MonoBehaviour
{
public void ShowActiveSceneNames()
{
foreach (string name in SceneUtil.GetActiveSceneNames())
{
Debug.Log(name);
}
}
}


現在のシーンをアンロードし、指定したScene群を読み込む


  • もっと綺麗に書ける気がするけどざっくり

using UnityEngine.SceneManagement;

using System.Collections.Generic;
using System.Linq;

public static class SceneUtil
{
public static void MoveScenes(List<string> sceneNames)
{
List<string> activeSceneNames = GetActiveSceneNames();
Dictionary<string, bool> activeSceneNameMap = activeSceneNames.ToDictionary(name => name, name => true);
Dictionary<string, bool> sceneNameMap = sceneNames.ToDictionary(name => name, name => true);

// シーンのロード
// シーンが空にならないように先に行う
// 既に読み込まれている場合、そのまま利用する
foreach (string sceneName in sceneNames)
{
if (!activeSceneNameMap.ContainsKey(sceneName))
{
SceneManager.LoadScene(sceneName, LoadSceneMode.Additive);
}
}

// シーンのアンロード
// 読み込むシーンに指定されている場合はアンロードしない
foreach (string activeSceneName in activeSceneNames)
{
if (!sceneNameMap.ContainsKey(activeSceneName))
{
SceneManager.UnloadScene(activeSceneName);
}
}
}

public static List<string> GetActiveSceneNames()
{
int sceneCount = SceneManager.sceneCount;
List<string> activeSceneNames = new List<string>();
for (int i = 0; i < sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
activeSceneNames.Add(scene.name);
}
return activeSceneNames;
}
}

using UnityEngine;

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

public class SceneTest : MonoBehaviour
{
public void MoveScenes()
{
List<string> sceneNames = new List<string>() { "stage1", "stage2", "stage3" };
SceneUtil.MoveScenes(sceneNames);
}
}


Sceneを跨いで使用するGameObjectを用意する


Editor拡張でSceneを取り扱う


例) 全てのシーンのTextComponentを指定したフォントに置き換える君