LoginSignup
3
1

More than 3 years have passed since last update.

【Unity】コルーチンとシーン遷移

Last updated at Posted at 2019-10-30

やりたいこと

  • コルーチンについての理解
  • コルーチンを用いたフェードイン・フェードアウトの実装

コルーチンの最小構成

コルーチンの定義

    IEnumerator  Fadeout() {
      yield return null;  
    }
  • 戻り値の型はIEnumerator
  • 戻り値は yield return ~~~;

コルーチンの呼び出し

   StartCoroutine("Fadeout");
   StartCoroutine(Fadeout());
  • メソッドを渡す。 (おそらくリフレクションを利用している。)
  • コルーチンの定義と呼び出しは同一クラスである必要がある。 (別クラスである場合、エラーが発生する。)

コルーチンの呼び出し順序

テストコード

public class Fade : MonoBehaviour
{
    void Update()
    {
        Debug.Log("BeginUpdate");
        if (Input.GetKeyDown(KeyCode.A))
        {
            Debug.Log("BeginFadeout");
            StartCoroutine("Fadeout");
            Debug.Log("EndFadeout");
        }
        Debug.Log("EndUpdate");
    }

    public IEnumerator  Fadeout()
    {
        for (int i = 1; i <= 3; i++)
        {
            Debug.Log("Fadeout : " + i + "回目");
            yield return null;
        }
    }
}

ログ

--- 1フレーム目 ---
BeginUpdate
BeginFadeout
Fadeout : 1回目
EndFadeout
EndUpdate
--- 2フレーム目 ---
BeginUpdate
EndUpdate
Fadeout : 2回目
--- 3フレーム目 ---
BeginUpdate
EndUpdate
Fadeout : 3回目

実行結果

  • 1フレーム目は通常のメソッドと同じ振る舞いをする。
  • 2フレーム以降は自動で実行され、順序はUpdate()とは別のタイミングである。

コルーチンについての理解を深める。

1フレームに一度実行する。

  yield return null;

コルーチンを一定時間ごとに実行する。

 yield return new WaitForSeconds(1.0f); // 1秒ごと

コルーチンを途中で終了する。(以降の処理は呼ばれない。)

  yield break;

全レンダリング完了後に実行する。

  yield return new WaitForEndOfFrame();

すべてのコルーチンを停止する。

  StopAllCoroutines();

※すべてのというのはそのクラス内(MonoBeheiver)ということ。別のクラスやオブジェクトには影響しない。

フェードイン・フェードアウトの実装

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

public class FadeSceneManager : MonoBehaviour
{
    private static Canvas canvas;
    private static Image image;

    // シングルトン
    private static FadeSceneManager singlton;
    public static FadeSceneManager Instance
    {
        get {
            if (singlton == null)
            {
                Init();
            }
            return singlton;
        }
    }
    private FadeSceneManager() { }
    private static void Init() {
        // Canvas作成
        GameObject canvasObject = new GameObject("CanvasFade");
        canvas = canvasObject.AddComponent<Canvas>();
        canvas.renderMode = RenderMode.ScreenSpaceOverlay;
        canvas.sortingOrder = 100;
        // 用途不明 (3Dになった際に必要になる?)
        // canvasObject.AddComponent<GraphicRaycaster>();

        // Image作成
        image = new GameObject("ImageFade").AddComponent<Image>();
        image.transform.SetParent(canvas.transform, false);
        // 画面中央をアンカーとし、Imageのサイズをスクリーンサイズに合わせる。
        image.rectTransform.anchoredPosition = Vector3.zero;
        Camera camera = GameObject.Find("Main Camera").GetComponent<Camera>();
        image.rectTransform.sizeDelta = new Vector2(Screen.width, Screen.height);

        // 遷移先シーンでもオブジェクトを破棄しない。
        DontDestroyOnLoad(canvas.gameObject);

        // シングルトンオブジェクトを保持する。
        // newの場合、オブジェクトが正しく初期化されない可能性があるので、
        // Add - GetComponentを通して、オブジェクトを取得する。
        canvasObject.AddComponent<FadeSceneManager>();
        singlton = canvasObject.GetComponent<FadeSceneManager>();
    }

    // 画面遷移を行う。
    // interval - フェードイン,フェードアウトに要する時間(秒)
    public void LoadScene(float interval, string sceneName)
    {
        StartCoroutine(Fade(interval, sceneName));
    }

    private IEnumerator Fade(float interval, string sceneName)
    {
        float time = 0f;
        canvas.enabled = true;

        // フェードイン
        while (time <= interval)
        {
            float fadeAlpha = Mathf.Lerp(0f, 1f, time / interval);
            image.color = new Color(0.0f, 0.0f, 0.0f, fadeAlpha);
            time += Time.deltaTime;
            yield return null;
        }

        // シーン非同期ロード
        yield return SceneManager.LoadSceneAsync(sceneName);

        // フェードアウト
        time = 0f;
        while (time <= interval)
        {
            float fadeAlpha = Mathf.Lerp(1f, 0f, time / interval);
            image.color = new Color(0.0f, 0.0f, 0.0f, fadeAlpha);
            time += Time.deltaTime;
            yield return null;
        }
        // 描画を更新しない。
        canvas.enabled = false;
    }
}

ほとんど参考サイトの通りです。
メリット : ゲームオブジェクトを動的に作成するため、初期配置が不要。

参考サイト

コルーチン
C#におけるyieldの挙動

【Unity】シーン遷移時のフェードイン・フェードアウトを実装してみた
Unityシーン間のフェードインアウトを2行で実現できる簡単スクリプト

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1