やりたいこと
- コルーチンについての理解
- コルーチンを用いたフェードイン・フェードアウトの実装
コルーチンの最小構成
コルーチンの定義
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;
}
}
ほとんど参考サイトの通りです。
メリット : ゲームオブジェクトを動的に作成するため、初期配置が不要。
参考サイト
【Unity】シーン遷移時のフェードイン・フェードアウトを実装してみた
Unityシーン間のフェードインアウトを2行で実現できる簡単スクリプト