Unityではゲームをシーンという単位で作成します。別のシーンに遷移を行う際、ロード処理が重たく固まってしまったり、ぱっと切り替わった表現になってしまうことがあります。そこで今回はシーンの加算とそれを利用したシーンのトランジション処理を作って見たいと思います。
どんなものができるのか
シーンの加算を利用して、なめらかなシーン切り替えを行うことが出来るようになります。
見た感じ
少し分かりづらいですが、下図は3つのシーンが利用されています
- Cubeのみのシーン
- Sphereのみのシーン
- クロスフェードを行うシーン
事前準備
今回は3つのシーンを用意しておきます。内容はスッカスカでも大丈夫。変化がわかりやすいものにしておくとベター
- コアシーン
- カメラもライトも無いシーン
- UIをOverlayで用意して、画面を隠す用のImageやPanelがあれば良し
- ただし一旦非表示にして、重ねたときに別のシーンが見えるようにしておくと制御しやすいです
- シーンその1
- 私の方ではCubeシーン。
- 動かない立方体が見えるだけ
- シーンその2
- Sphereシーン
- こちらも球が見えるだけのシーン
実際には各シーンではゲームの内容を実装します。また、Build Settingsに3つのシーンを登録する必要があります。シーンのロード時に必要になります。
シーンの加算方法
まずはCoreシーンにCubeシーンを重ねてみたいと思います。Unityの機能でも再現することが出来ますので、事前に問題ないことを確認してからプログラム実装していきましょう。
Unityの機能でシーンの加算を行う
プログラムで加算処理を実装する前に、Unityの機能で追加してみましょう。
- Coreシーンを開く
- プロジェクトビューの追加したいシーンを右クリック>Open Scene Additive
- 追加が出来たらヒエラルキーで2つのシーンが出ていることを確認。
- ついでにゲームビューからも両方のシーンが表示されていることを確認してください
なにもないシーンに、追加したシーンが表示されたらOK。
追加したシーンをもとに戻す
追加したシーンが不要になった場合、ヒエラルキーの削除したいシーンマークの右の・・・を選択して「Remove Scene」を選択すると削除することが出来ます。これはヒエラルキーから取り除かれるだけで、シーンが完全に消えるわけではありません。
プログラムでシーンを追加する
ここからはCoreシーンをベースに作業を行います。作成するスクリプトは「SceneController」としましょう。
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneController : MonoBehaviour
{
private void Start()
{
// Load the other scene
SceneManager.LoadScene("Cube", LoadSceneMode.Additive);
}
}
スクリプトが編集出来たら、Coreシーンに空のGameObjectを作成し、アタッチします。その状態でゲームを実行するとCubeシーンを追加でロードすることが出来ます。
この時Coreシーンが消えていないことも合わせて確認してください。
DOTweenを準備
では今回の仕上げとして、Cubeシーンをフェードアウトで隠れたあとに、Sphereシーンを呼び出して見たいと思います。フェードアウトを行う処理として、DOTweenを利用します。DOTweenを使ったことがない人は、こちらを参考にセットアップしてみてください。とても便利なアセットなのでオススメです。
シーンを遷移させる処理
今回はゲームをクリックするとシーンが遷移する処理を作って見たいと思います。
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using DG.Tweening;
public class SceneController : MonoBehaviour
{
[SerializeField] private Image fadeImage;
private void Start()
{
// Load the game scene
SceneManager.LoadScene("Cube", LoadSceneMode.Additive);
}
private void Update()
{
if (Input.GetMouseButton(0))
{
// Fade out the image
fadeImage.DOFade(1, 1).OnComplete(() =>
{
// Unload the current scene
SceneManager.UnloadSceneAsync("Cube").completed += (op) =>
{
Debug.Log("Unload complete");
// Load the next scene
SceneManager.LoadScene("Sphere", LoadSceneMode.Additive);
// Fade in the image
fadeImage.DOFade(0, 1).SetEase(Ease.InQuad).OnComplete(() =>
{
Debug.Log("Fade in complete");
});
};
});
}
}
}
あとは画面内を1クリックすることでシーンの中身が切り替わってくれます。
こちら連打対応はしていません。クリックするのは1回だけになっているのを注意!
課題点
今回のプログラムでは、実践で利用するには少し機能が不足しています。以下の問題点を理解しつつ、改善しながらゲームに組み込んでください。
- 現在ロード中のシーンを把握する
- 上記プログラムでは文字列を直接打ち込んでいるため、実際にロードされているシーンが把握出来ない
- ロード時に何のシーンを読み込んだかを覚えておきましょう
- インスペクターの連携が出来ない
- UIとゲーム内のオブジェクトをインスペクターなどで紐付けることが出来ない
- これは、独立したシーン同士は相互に参照できるかどうかが保証出来ないためである
- 別途連携させるための仲介するプログラムが必要
コメント