【Unity】フェードアウトするシーン間遷移の実装


背景

Unityにおけるシーン切り替えの処理にはSceneManager.LoadScene
関数を用いるが、以下の難点がある。
・ロードが発生する時間画面が止まってしまう
・単純な画面切り替えなので演出が物足りなく感じる
これら解消のためフェードアウト風の処理をはさむことにした。

バージョン

・Unity - 2019.3.13f1

通常の遷移

比較のため、はじめにSceneManager.LoadScene関数によって
scene_1からscene_2へどのように遷移するか確認する。

 画面

 スクリプト

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

public class Scene_Controller : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Invoke("transition", 0.5f);
    }

    // Update is called once per frame
    void Update()
    {

    }

    void transition()
    {
        SceneManager.LoadScene("scene_2");
    }
}

本題

フェードアウト遷移を以下の手順で実現する

  1. マスク用のオブジェクトを用意
  2. スクリプトを編集

1. マスク用のオブジェクトを用意

Hierarchyタブ上で右クリック > UIRaw Imageを選択

inspectorフィールドのColorを黒に変更する


※オブジェクト名は便利のため、Masking_Imageという名前に変更した。

2. スクリプトを編集

Scene_Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class Scene_Controller : MonoBehaviour
{
    public GameObject mask;
    // Start is called before the first frame update
    void Start()
    {
        //raw imageの取得
        mask = GameObject.Find("Masking_Image");

        //画面全体に広げる
        mask.GetComponent<RectTransform>().sizeDelta = new Vector2(Screen.width, Screen.height);

        //透明度を最大にする
        Color color_before = mask.GetComponent<RawImage>().color;
        color_before.a = 0.0f;
        Color color_after = color_before;
        mask.GetComponent<RawImage>().color = color_after;

        //非活性にし画面を操作できるようにする
        mask.GetComponent<RawImage>().enabled = false;

        //画面遷移
        transition();

    }

    // Update is called once per frame
    void Update()
    {

    }

    void transition()
    {
        //フェードアウト処理を呼ぶ
        Call_Fade();
        //シーン切り替え
        Invoke("Scene_2", 0.5f);
    }

    void Scene_2()
    {
        SceneManager.LoadScene("scene_2");
    }


    public void Call_Fade()
    {
        mask.GetComponent<RawImage>().enabled = true;
        StartCoroutine("Fade", mask);
    }

    //フェードアウト処理
    IEnumerator Fade(GameObject mask)
    {
        for (int i = 0; i < 100; i++)
        {
            Color color = mask.GetComponent<RawImage>().color;
            color.a += 0.01f;
            mask.GetComponent<RawImage>().color = color;


            if (i == 99)
            {
                yield break;
            }
            else
            {
                yield return null;
            }
        }
    }
}

簡単な解説

Start()でマスク画像の最大化、透明化、非活性化を行っている
transition()で画面遷移とフェードアウト処理を同時に開始する

コルーチンを使用するメリット

フェードアウト処理にコルーチンを使用することにより、非同期処理で
画面遷移を同時に行うことができる。

本来の非同期処理というのはマルチスレッド(複数処理を並行して行う)のことを指すが
コルーチンはシングルスレッドであり、擬似的に非同期処理を実装できる仕組みらしい。

今回のケースでは1フレームの中でまずマスク画像の透明度を0.01下げ、
残りの尺で画面遷移処理をする。これを毎フレーム繰り返すことであたかも
フェードアウト処理と画面遷移を同時に行っているように見せている、ということになる。

結果画面

おわりに

今回の内容は自分と同じように個人でゲームを作成している方の助けになればと思い、書きました。
ローディング画面までガッツリ作りたい派の方々には不足が多いかもしれません‥orz
自己流な部分が多いと思いますので、指摘・感想等自由にコメント欄にお寄せ頂ければと思います。