tomo_manaのブログ

tomo_manaのブログ

Unityで一からゲームを作る方法を紹介しています。

Unity学習#29-1 シーンのロード/アンロード (Unity 2019.4.4f1)

戦闘シーンの追加にあたり、シーンの基本的な操作について調べました。


備忘のために、スクリプトからシーンを操作する時に必要になる関数などをまとめました。

シーン

シーンはプロジェクト設定を記述したテキストファイルで、それ自体が一つのクラスインスタンス化します。ただしクラスインスタンスとしてアクセスできるのはHierarchy ウィンドウ上でシーンの直下にぶら下がっているGameObject または Transform だけです。

ファイルとしてのシーン

ファイルとしてのシーンは、プロジェクトの設定ファイルです。通常はProject > Asset > Scene に作成されます。拡張子は .unity です。

f:id:tomo_mana:20210223001457p:plain
UnityEditor上でのScene
f:id:tomo_mana:20210223001659p:plain
FileExplorer上でのScene (.Unity)

ファイルの中身はテキストで、シーンに属するゲームオブジェクトなどの情報が記述されています。

クラス・インスタンスとしてのシーン

シーンは、後述するシーンマネージャーによって、インスタンスにできます。通常は現在実行中のシーンがインスタンスとして動いていて、開発者はシーンをあまり意識しなくてもスクリプトを実装できます。シーンにはスクリプトを付与できません。

シーンの識別子

後述するシーンマネージャーを使って、以下の識別子でシーンを探すことができます。

(シーンの識別子)

識別子 Scene変数 SceneManagerインターフェース
BuildSettingsのID Scene::buildIndex SceneManager.GetSceneByBuildIndex()
シーン名 Scene::name SceneManager.GetSceneByName()
ファイルパス Scene::path SceneManager.GetSceneByPath()

しかしながら、シーンは他のプレハブと同じように、同一のシーンを複数ロード(インスタンス化)できます。そのため、シーンを複製する場合は、以下のインターフェースに頼ることになります。

(シーンマネージャー上のリスト番号)

識別子 SceneManagerインターフェース
シーンマネージャー上のリスト番号 SceneManager.GetSceneAt()

シーンマネージャー

複数のシーンを並列的に動かす仕組みです。シーンをリストとして持ち、前述のリスト番号で各シーンにアクセスできます。シーンマネージャーを使用するには以下をインクルードします。

using UnityEngine.SceneManagement;

シーンマネージャーはstaticなインターフェースを提供します。

(シーンマネージャーのインターフェース)

機能 インターフェース
シーンのロード LoadSceneAsync("シーン名", LoadSceneMode.Additive)
現在選択されたシーン Scene = GetActiveScene()
選択されたシーンの変更 SetActiveScene(Scene)
シーンのアンロード UnloadSceneAsync()

(シーンのインターフェース)

状態 定義ラベル
シーンがロードされたか Scene::isLoaded


以下、各インターフェースについてまとめます。

シーンのロード

シーンのロードはシーンマネージャーから実行します。

SceneManager. LoadSceneAsync("シーン名", LoadSceneMode.Additive);

f:id:tomo_mana:20210223000852p:plain

シーンがロードされたか

シーンがロードされたかどうかは、シーンの状態で確認します。

SceneManager.GetSceneByName("シーン名").isLoaded

シーンをロードする条件

シーンをロードするために、あらかじめBuildSettingsにシーンを登録しておく必要があります。
(1) Unityエディタメニューから、File > BuildSettings
(2) 登録するシーンをBuildSettings画面にドラッグ&ドロップ
(3) BuildSettings画面を閉じます。(Buildボタンなどは押さなくてよい)

注意点1: Main Camera の多重化

LoadSceneMode.Additive でシーンをロードした時、Main Camera が Active だと、選択された画面に Additive されたカメラが適用されて、変な表示になることがあります。ロードするシーンは、MainCamera を 非Active にしておく方が良さそうです。

注意点2: AudioListenerの多重化

AudioListener は 2つ以上あると以下の警告が出ます。こちらも、Main Camera と同じく、ロードされた時に非Activeにして、同時に2つの AudioListenerを立ち上げないようにする必要があります。

現在選択されたシーン

LoadSceneMode.Additive で呼ばれたシーンはロードされただけでは選択状態になりません。選択状態にあるシーンだけ、GameObjectなどの作成が可能なようです。選択されているシーンは以下の関数で確認ができます。

Scene scene = SceneManager.GetActiveScene();

シーンの切り替え(シーンがロードされた状態で)

選択されたシーンの変更は以下の関数で行います。

Scene newScene = GetSceneAt( 1 );
SceneManager.SetActiveScene( newScene );

シーンのアンロード

シーンのアンロードは以下の関数で行います。

SceneManager.UnloadSceneAsync("シーン名");

f:id:tomo_mana:20210221230626p:plain

アンロードに関しても、注意点があります。

注意点1: Activeなシーンが削除された場合、ほかにActiveになれるシーンが選択される

しかしながら、通常はバグでもない限り、Activeなシーンを削除しないと思います。

注意点2: 最後の一つのシーンは削除できない

アンロードしようとするシーンが最後の1つだった場合、以下の警告が出て削除できません。こちらも通常は行わないオペレーションですね。
f:id:tomo_mana:20210221230708p:plain
Unloading the last loaded scene Assets/Scenes/FieldScene.unity(build index: 0), is not supported. Please use SceneManager.LoadScene()/EditorSceneManager.OpenScene() to switch to another scene.
UnityEngine.SceneManagement.SceneManager:UnloadSceneAsync(Scene)


(以上)