2020/11/09
というわけで、今回はUnityにおけるシーン遷移時のカメラのフェードイン・アウト処理に関するお話です。
シーン遷移時のフェードといえば、iTween
のCameraFadeTo()
を使っていたのですが、そちらではUIを含めたフェードが上手くいかなかったので、今回作り直してみることにしました。
私のゲームの場合、全画面に共通して存在するシングルトンのマネージャクラスがあるので、そちらにフェードに関する処理を実装していきます。
以下はマネージャクラスのフェードに関する処理のスクリプトです。
// Canvasの参照 protected Canvas currentCanvas; // カメラフェード用オブジェクトの参照 protected GameObject fadeObject; protected Image fadeImage; void Start() { // カメラフェード用オブジェクトの用意 currentCanvas = GameObject.FindObjectOfType<Canvas>(); CreateFadeObject(); // シーン遷移後のイベント追加 SceneManager.sceneLoaded += (scene, loadSceneMode) => { currentCanvas = GameObject.FindObjectOfType<Canvas>(); CreateFadeObject(); }; } /// <summary> /// カメラフェード用のオブジェクトを作成・準備する /// </summary> protected void CreateFadeObject() { fadeObject = new GameObject("CameraFade"); fadeObject.transform.SetParent(currentCanvas.transform); fadeObject.transform.position = Vector3.zero; fadeImage = fadeObject.AddComponent<Image>(); fadeImage.color = Color.black; fadeImage.CrossFadeAlpha(1, 0, true); fadeImage.rectTransform.sizeDelta = new Vector2(1500, 1000); fadeImage.rectTransform.anchoredPosition = Vector3.zero; }
ゲーム上の全シーンにフェード用の画像を用意するのは効率が悪いため、シーンロード時にマネージャクラスから生成するようにしました。作ったGameObjectをCanvas
の子オブジェクトにすること、追加するImage
のサイズは画面をすっぽり覆うくらい大きくすることがポイントです。
次に実際にフェードイン・アウトする処理を実装します。フェード自体はImage
クラスのCrossFadeAlpha()
を使うことで簡単に実現できますが、そのままではUIの表示順の関係で上手くいきません。そこでフェード前にTransform.SetSiblingIndex()
で表示順を一番前にもってきます。
/// <summary> /// シーンをロードする /// </summary> /// <param name="name"></param> /// <param name="fade_time"></param> public void LoadScene(string name, float fade_time = GameConstants.SCENE_FADE_TIME) { fadeImage.transform.SetSiblingIndex(9999); fadeImage.CrossFadeAlpha(1f, fade_time, true); DOVirtual.DelayedCall(fade_time, () => { SceneManager.LoadScene(name); }); } /// <summary> /// シーン開始時のフェードイン処理を行う /// </summary> /// <param name="fade_time"></param> public void OnSceneStartFadeIn(float fade_time = GameConstants.SCENE_FADE_TIME) { fadeImage.transform.SetSiblingIndex(9999); fadeImage.CrossFadeAlpha(0, fade_time, true); DOVirtual.DelayedCall(fade_time, () => { fadeImage.transform.SetSiblingIndex(0); }); }
フェードアウトの場合はシーン遷移開始時がほとんどなので、シーンの読み込みと同時にフェード処理を書いています。
フェードインの方は各シーンのマネージャクラスから呼び出して使用します。私の場合は上述の通りシングルトンになっているため、GlobalManager.GetInstance().OnSceneStartFadeIn()
という感じで呼び出せるようにしています。
またフェード完了後は再度SetSiblingIndex()
を呼び出し、フェード用画像の表示順を一番後ろにします。
今回は自力で作りましたが、フェード処理によさげなライブラリもあるようなので、もっとシャレオツな演出にしたい場合は検討してみるのも良いかもしれません。