Unityのシーン遷移作ってみた(非同期、フェイド付き)

#効果
ゲームの中でよく使っているフェイド付きシーン遷移作りました。効果はこんな感じです！
![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451854/3b58b702-9a4e-9378-2747-a5d94ec43fcd.gif)

#仕様

仕様はこんな感じです。

1. Prefabをシーン内配置したら使える
2. 非同期(ロード画面付き) 
3. フェイドアウト、フェイドイン付き
4. 遅延実行、ロード完成の時自動シーン遷移するかどうか指定できる

#流れ 

####1. シーン遷移用のPrefab

![スクリーンショット 2021-09-18 130131.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451854/d06ead5f-f651-0b80-15d2-15e75391ca57.png)
シーン遷移本体Prefab
　フェードアニメーション (UICanvas、Animatorコンポーネント必要)
　　フェードアニメーション用画像 (UI Image、画面全体サイズと同じの黒画像、Canvas Groupコンポーネント必要)
　ロード画面
　　プログレスバー (今回はUI Sliderを使った)
　　プログレス文字 (今回はUI Textを使った)

####2. フェイドイン、フェイドアウトアニメーション作る

今回は黒画像一枚のアルファを制御する形で作ります。
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451854/9c87b3cc-4ba3-f3f8-3424-cbc933e83720.gif)

フェードアニメーション用画像をこんな感じです。
![スクリーンショット 2021-09-18 130838.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451854/c7c3bece-e2d5-8890-620c-e499a8bb25d6.png)

アニメーションを作る。(Alphaを0から1、Alphaを1から0　2種類作ること)
![スクリーンショット 2021-09-18 131242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451854/923a8491-c176-d653-c116-c62b6bc4b3bf.png)



####3. フェードアニメーションをAnimatorコンポーネントつける

![スクリーンショット 2021-09-18 130314.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451854/4e556718-1e89-4d15-525f-e4b49eb59d30.png)
Animator内はこんな感じです。
開始後はフェイドインする、StartがTriggerになったらフェイドアウトする。

####4.シーン遷移本体Prefabをコード追加
![スクリーンショット 2021-09-18 135415.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451854/0c68ef8f-2afa-4a38-bc53-de0b8abb3498.png)

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class LevelLoader : MonoBehaviour
{
    // シーン遷移のアニメーション
    [Header("シーン遷移アニメーション")]
    public Animator transition;
    // フェイドアウト開始から実際にシーン遷移開始までの時間
    [Header("シーン遷移時間")]
    [Range(0.0f,5.0f)]
    public float transitionTime = 1f;
    // フェイドアウト開始までの遅延時間
    [Header("遅延実行")]
    [Range(0.0f,5.0f)]
    public float DelayActiveTime = 0.5f;
    // ロード完成になったらすぐ遷移するかどうか
    [Header("ロード完成の時自動シーン遷移")]
    public bool TransitionAuto_LoadFinish = false;

    // いろいろ
    private Canvas loadingcanvas;
    private Slider loadingbar;
    private Text loadingtext;
    // 非同期ロード用
    private AsyncOperation LoadOperation;

    void Awake()
    {
        transform.GetChild(0).gameObject.SetActive(true);
    }

    // Start is called before the first frame update
    void Start()
    {
        // いろいろ代入
        loadingcanvas = transform.GetChild(1).gameObject.GetComponent<Canvas>();
        loadingbar = loadingcanvas.transform.GetChild(0).GetComponent<Slider>();
        loadingtext = loadingcanvas.transform.GetChild(1).GetComponent<Text>();
    }

    // ほかのシーンロートしたい時この関数を使う(シーンのインデックス)
    public void LoadScene(int index)
    {
        StartCoroutine(LoadLevel(index));
    }

    // シーンリロートしたい時この関数を使う
    public void ReloadScene()
    {
        var acrtivesceneindex = SceneManager.GetActiveScene().buildIndex;
        StartCoroutine(LoadLevel(acrtivesceneindex));
    }

    // 内部用ロードコルーチン
    private IEnumerator LoadLevel(int index)
    {
        // 遅延
        yield return new WaitForSeconds(DelayActiveTime);
        // フェードアウトスタート
        transition.SetTrigger("Start");
        // 待ち
        yield return new WaitForSeconds(transitionTime);
        // ロード開始
        StartCoroutine(LoadAsync(index));
    }
    
    // 非同期ロード処理
    private IEnumerator LoadAsync(int s_index)
    {
        LoadOperation = SceneManager.LoadSceneAsync(s_index);
        LoadOperation.allowSceneActivation = TransitionAuto_LoadFinish;
        // ロード画面表示
        loadingcanvas.enabled = true;

        while (!LoadOperation.isDone)
        {
            InLoading();
            yield return null;
        }

    }
    
    // ロード画面内処理
    private void InLoading()
    {
        /* 
        ロード画面内したい処理ここで書く
        */
        
        // プログレスバーと文字を更新する
        float progress = Mathf.Clamp01(LoadOperation.progress / .9f);
        loadingbar.value = progress;
        loadingtext.text = progress * 100f + " %";


        if (!LoadOperation.allowSceneActivation)
        {
           /*
           ロード完成から実際にシーン遷移までの処理ここで書く
           (ここはロード完成後スペースキー押したら遷移の処理にします)
           */
           if (Input.GetKeyDown(KeyCode.Space))
           {
              LoadOperation.allowSceneActivation = true;
           }
        }
    }

}
```