Help us understand the problem. What is going on with this article?

[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を指定したフォントに置き換える君

unity-game-dev-guild
趣味・仕事問わずUnityでゲームを作っている開発者のみで構成されるオンラインコミュニティです。Unityでゲームを開発・運用するにあたって必要なあらゆる知見を共有することを目的とします。
https://unity-game-dev-guild.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした