2013年12月1日日曜日

【Unity】シーン遷移時のフェードイン・フェードアウトを実装してみた

お久しぶりです。
前回の記事からもう1週間も経ってるんですね。ブログ続けるの難しい…。

さて今日はScene遷移時のフェードイン・フェードアウトを実現できたのでまとめておきます。
フェードって言っても色々あると思いますけど
今回実装したのはだんだん暗くなって、だんだん明るくなるシンプルなアレです。

イメージ

  • だんだん暗くなり、Sceneが切り替わり、だんだん明るくなる
  • 暗くなる(明るくなる)時間は好きに指定したい
  • Application.LoadLevelと似たような感じで呼び出したい

デモ


Hosted by UnityRoom.com

ダウンロード

2015/03/22追記
大きく作り替えるとともにGitHubに公開しました。
ダウンロードおよび使い方はGitHubをご確認ください -> Unity-FadeManager | GitHub

従ってここから下は古い情報です。

実装

1時間弱で完成。
長いのでソースは一番下に載せておきます。


使い方

SingletonMonoBehaviour.csを用意

下記の記事にある"SingletonMonoBehaviour.cs"を用意しておく。
【前の記事】シングルトンの実装についてはこちら
【Unity】なんちゃらManagerクラスを作ろう(シングルトン)

FadeManagerの配置

・空のGameObjectを作成
・名前をFadeManagerにする
・AddComponentでFadeManagerを追加


呼び出す

Application.LoadLevelの代わりに下記のように書く
・FadeManager.Instance.LoadLevel("シーン名",フェード時間)
FadeManager.Instance.LoadLevel("Scene2",1.0f);

こんな感じ。
これだと1秒かけて暗くなり、Scene2に切り替わり、1秒かけて明るくなる。
いい感じ。


ソース

FadeManager.cs

using UnityEngine;
using System.Collections;

/// <summary>
/// シーン遷移時のフェードイン・アウトを制御するためのクラス
/// </summary>
public class FadeManager : SingletonMonoBehaviour<FadeManager>
{
 /// <summary>暗転用黒テクスチャ</summary>
 private Texture2D blackTexture;
 /// <summary>フェード中の透明度</summary>
 private float fadeAlpha = 0;
 /// <summary>フェード中かどうか</summary>
 private bool isFading = false;
 
 public void Awake ()
 {
  if (this != Instance) {
   Destroy (this);
   return;
  }

  DontDestroyOnLoad (this.gameObject);

  //ここで黒テクスチャ作る
  this.blackTexture = new Texture2D (32, 32, TextureFormat.RGB24, false);
  this.blackTexture.ReadPixels (new Rect (0, 0, 32, 32), 0, 0, false);
  this.blackTexture.SetPixel (0, 0, Color.white);
  this.blackTexture.Apply ();
 }
  
 public void OnGUI ()
 {
  if (!this.isFading)
   return;

  //透明度を更新して黒テクスチャを描画
  GUI.color = new Color (0, 0, 0, this.fadeAlpha);
  GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), this.blackTexture);
 }

 /// <summary>
 /// 画面遷移
 /// </summary>
 /// <param name='scene'>シーン名</param>
 /// <param name='interval'>暗転にかかる時間(秒)</param>
 public void LoadLevel(string scene, float interval)
 {
  StartCoroutine (TransScene (scene, interval));
 }
 
 
 /// <summary>
 /// シーン遷移用コルーチン
 /// </summary>
 /// <param name='scene'>シーン名</param>
 /// <param name='interval'>暗転にかかる時間(秒)</param>
 private IEnumerator TransScene (string scene, float interval)
 {
  //だんだん暗く
  this.isFading = true;
  float time = 0;
  while (time <= interval) {
   this.fadeAlpha = Mathf.Lerp (0f, 1f, time / interval);      
   time += Time.deltaTime;
   yield return 0;
  }

  //シーン切替
  Application.LoadLevel (scene);
  
  //だんだん明るく
  time = 0;
  while (time <= interval) {
   this.fadeAlpha = Mathf.Lerp (1f, 0f, time / interval);
   time += Time.deltaTime;
   yield return 0;
  }

  this.isFading = false;
 }

}

ポイント

・実行にはSingletonMonoBehaviourクラスが必要です。→こちら
・Application.LoadLevelの代わりにこのクラスのLoadLevelメソッドを使います。
・第一引数に遷移先シーン名を指定
・第二引数にフェードにかかる時間を指定

まとめ

Application.LoadLevelだと呼び出してから実際に切り替わるまでにタイムラグがあるので
ユーザーがボタンを押してからの反応が遅く、あれ?押したよね?ってなります。

これはユーザーにしたらすごいストレスですよね。
ボタンっぽくないボタンとか、押しても反応がないボタンとかしんどい。

今回のフェードを実装したことで
読み込みが多少遅くてもボタンを押した瞬間に
暗くなり始めるのでユーザーには多少親切になりました。
(そもそも読み込み早くしろよって言われればその通りですけど…^^;)

しばらくこれで使ってみよう。

それじゃまた!
Unity系記事まとめ

スポンサーリンク

Related Posts Plugin for WordPress, Blogger...