【Unity】Unityでトランジションを使用した綺麗な場面転換(uGUI対応版)
以前に紹介した「場面転換」をよりスムーズな感じで行う処理ですが、uGUIに対応させるついでにUI単位で削除出来るようにしました。
UnityでuGUIのトランジション。パターンはマスク画像(白黒画像)を使用。トランジションするUIの下にあるUIも一緒に消える pic.twitter.com/YmJPSmAowy
— 椿 (@tsubaki_t1) 2015, 10月 28
新しいFade Cameraは、ここからダウンロードできます。
サンプルはここからダウンロードできます。
目次
新しいFade Camera
今回のバージョンから、uGUIを基本として動作するようになっています。
「最前面でuGUIのImageがエフェクトをかけて場面転換する」理屈です。
これの応用で、「テキストを残して残りを場面遷移」といった表現も可能になりました。
もう一つの機能は、UIのトランジションです。
今までのトランジションは画面の最前面にエフェクトを載せる形でエフェクトを起こしていましたが、このUIトランジションは「UIを消すエフェクトを起こします」
つまり今までのUI出現パターンである「画面が居に移動する」「透明にする」「別のUIで隠す」以外の選択肢として、UI自体をエフェクトで消すことを可能になる訳です。

これらのエフェクトは、白黒マスクを元にして作成します。この白い所から黒い所にかけてエフェクトが走ります。
マスク画像はFor you様をはじめとして、幾つかのページから入手することが出来ます。
このマスクは「ルール画像」と呼ばれてる事もあります。

ちなみにUnity 5.2で動作します。
普通のトランジション設定
まず普通のトランジション(画面最前面を塗りつぶす)についてです。
前回と違い、計算簡略化のため少しテクスチャに設定します。
まずマスク画像をインポートします。

インポートしたマスク画像を白黒画像からアルファ画像へ変換します。
Texture TypeをTextureに選択し、Alpha from GrayscaleとAlpha Is Transparencyにチェックを入れて、Applyで更新します。


Fade>FadeCanvasをシーンに配置し、トランジションのマスクを設定します。
トランジションのマスクはFadeCanvas/FadeImageのFadeImageコンポーネントのMaskTextureが該当します。


Mask Textureを差し替えれば、UIのエフェクトを差し替える事が出来ます。
とりあえず簡単に操作出来るように、FadeコンポーネントのCutoutRangeを操作するとフェードするようになっています。

このシンプルなトランジションでは2パターンのフェードを行えます。
一つは前回と同じくアルファによるトランジション、もう一つはカットアウト、つまりほぼアルファ画像が無いパターンです。
アルファによるトランジションは全体的に綺麗でギザギザが見えにくく、カットアウトによるトランジションはキッパリと抜けますがアルファがほぼありません(正確にはカットアウト”風”です)。
この切り替えはマテリアルの差し替えで行います。UI-Fade-Alphaがアルファを使ったフェード、UI-Fade-Cutoutがカットアウト風のフェードです。

UIトランジション設定
UIトランジションは少しだけ複雑です。
まずFadeMaskをCanvas以下に配置します。
あとはFadeMask以下にUI要素を配置していきます。

UIトランジションは使用しているMaterialのMaskTextureを差し替えるとマスクが切り替わります。また、FadeのCutoutRangeを動かすことでフェードを行います。
残念な事にUIトランジションはアルファには対応していないので、カットアウト風のエフェクトのみになります。このエフェクトの解像度は「Texture」が元になっているので、解像度が低いと感じた場合はFadeUIのTextureを更新します。
ただ高解像度はモバイルでは重いかもしれません。


スクリプトによる制御
FadeCamera1から「スクリプト制御は各々に任せた方が良い(サンプルはプロダクトと上手くマッチしない方が多い)」と思ったので、サンプル程度の物しか置いてません。
サンプルでは、下記のような形でフェードを制御します。なお今回はフェードが複数存在する可能性があるのでFadeはシングルトンではありません。
下のコードは、「1秒間フェードインし、その後フェードアウトする」処理です。
using UnityEngine;
using System.Collections;
public class FadeTest : MonoBehaviour
{
[SerializeField]
Fade fade = null;
public void OnClick()
{
fade.FadeIn (1, () =>
{
fade.FadeOut(1);
});
}
}
フェード回りの処理を何とかしたい場合、Fade.csを直すと色々と出来ます。
関連
売り切りとF2Pの話~あるいはめんどうくさい 課金とゲームデザイン~
中々に興味深い話なのでメモ。
大雑把に言えば、以下のような内容な気がします。
- 最近のF2Pゲーム開発にかかる費用と内訳
- F2P環境における売り上げの期待値、
DAU・課金率・ARPPU(夢中度)の見方 - 「売り切りゲーム」と「F2P」の違い
- 売り切りの作りをF2Pにすると奇跡が起こらないと儲からない。
何故? - F2Pの歴史
- F2Pは何処で儲けるのか
- この先生 きのこる為の戦略
- 海外と日本の違い
要するに、売切りモデルからF2Pにシフトする場合、ゲームデザインから儲けのモデルを作らないと駄目…というお話な認識です。
確かに、ゲーム市場がF2Pに移行した現状だと、この辺り良く考えないと凄い悲しい事になるような気がします。
関連
【Unity】ScriptableSingletonでエディタウィンドウ間の情報共有
目次
エディタは値を忘れる
Unityエディタは実は物忘れが激しいです。
何が言いたいかと言えば、エディタウィンドウ等で使用されているstaticな変数を「ゲームの再生時やコンパイル時に忘れる」という、中々面白い挙動を行います。
これは単一のウィンドウ内で完結している場合は全く問題は無いのですが、複数のウィンドウで情報を共有したい場合、非常に面倒くさい事になります。
例えば下の画像では、pushボタンを押した数だけカウントが進んでいくサンプルです。このサンプルではどのウィンドウから押しても数値を加算可能なようにstatic変数で値の共有を行っていますが、ゲーム再生時に初期化されてしまいます。

using UnityEngine;
using System.Collections;
using UnityEditor;
public class EditorWIndowTest : EditorWindow
{
static int clickCount = 0;
[MenuItem("Command/Show")]
static void Init()
{
EditorWIndowTest.CreateInstance ().Show ();
}
void OnGUI()
{
if (GUILayout.Button ("push")) {
clickCount ++;
}
EditorGUILayout.LabelField (clickCount.ToString ("000"));
}
}
ScriptableSingletonを使う
ScriptableSingletonを使えば、ゲーム再生時に消えない&データが共有できるオブジェクが作れます。
またScriptableSingletonの生存時間は「エディタを止めるまで」とかなり長く、一度インスタンス化が行われれば、エディタ上ではずっと使いまわすことが出来ます。
例えば上のコードを下のように書き直します。
using UnityEngine;
using System.Collections;
using UnityEditor;
public class EditorWIndowTest : EditorWindow
{ [MenuItem("Command/Show")]
static void Init()
{
EditorWIndowTest.CreateInstance ().Show ();
}
void OnGUI()
{
if (GUILayout.Button ("push")) {
ScriptableSingleton<EditowWindowTestData>.instance.count ++;
}
EditorGUILayout.LabelField (ScriptableSingleton<EditowWindowTestData>.instance.count.ToString ("000"));
}
}
public class EditowWindowTestData : ScriptableSingleton<EditowWindowTestData>
{
public int count;
}
大きな違いはstatic変数として持っていたCountの値を、新しく作成したEditorWindowTestDataクラスに持たせている事です。
これによって、ゲーム再生後もデータを失わせることなく、ウィンドウ間のデータ共有が出来る訳です。
感想
本当は「プロジェクト単位でデータを保存できる事」を期待していたのですが、Saveメソッドがあったりデータをロードできるっぽい内部構造をしている割に、全くこの手の操作には使えません。
またScriptableObjectとしてアセットをプロジェクトに保存し全体参照しようにも、起動時最初に呼び出した(保存したSOでなければコードで初期化されたSO)が呼ばれ、インスタンスが重複した場合「ひたすらにエラーログを出す」という微妙な仕様です。
せめてエディタ用APIじゃなければ、それでもマシと思えたのですが…
うーん。