画面のフェードイン・アウトが思ったよりコード量があるので、前回と今回の2回の記事に分けました。今回は第9回で作ったフェードイン・アウト処理と第8回のワープ処理をくっつけます。
フェードイン・アウトのインタフェース(第9回)
前回のフェードイン・アウト処理を参照するためには、以下を追加します。
コード
private FadeManager fader; // 処理 if ( fader.IsFading() == false ){ fader.FadeIn(); }
ただし、フェードイン・アウトの処理を行う間、ワープ処理は待つ必要があるので、ワープ処理内に状態を持たせる必要があります。
ワープの状態
状態遷移図
キャラクターがワープポイントに衝突した時、ワープポイントはフェードアウトを待ってワープします。ワープした後、フェードインを待ってワープポイントは再びキャラクターが衝突してくるのを待ちます。
これを状態遷移図にすると以下になります。
1) 衝突待ち
↓ 衝突
2) フェードアウト
↓ 完了
3) ワープ
↓ 完了※
4) フェードイン
↓ 完了
1) 衝突待ち
※実際は、3) ワープ処理は、同一平面での座標移動の場合は「待ち」が発生しないので、今回は状態でなく処理の一部にします。今後、マップの読み込みなどで時間がかかる場合は「待ち」にする可能性があるかもしれません。
状態遷移表
イベントと状態を整理して、状態遷移表を作ります。
ワープの修正
状態定義
状態を列挙体で定義します。
コード
enum WarpState { Idle, Triggered, FadeOut, FadeIn } private WarpState state;
イベント処理の追加
今回は、イベントが「衝突」以外はすべて「フェード処理完了」になるので、Update() 関数の中で一つのif文にまとめています。
コード
public class Warp : MonoBehaviour { // ワープ中の状態 enum WarpState { Idle, Triggered, FadeOut, FadeIn } private WarpState state; // Start is called before the first frame update void Start() { state = WarpState.Idle; } // Update is called once per frame void Update() { if( state != WarpState.Idle ){ if( fader.IsFading() == false ){ // 次の処理へ switch( state ){ case WarpState.Triggered: state = WarpState.FadeOut; break; case WarpState.FadeOut: state = WarpState.FadeIn; break; case WarpState.FadeIn: state = WarpState.Idle; break; default: break; } } } } void OnTriggerEnter2D (Collider2D other) { if( state == WarpState.Idle ) { state = WarpState.Triggered; } } }
衝突時の処理からワープ処理をくくりだす
isTriggerで使うことができたCollider2Dを直接使えなくなる(参照が変わる)ため、ワープポイントにぶつかったキャラクターCollider2Dをワープポイントは覚えておかなければなりません。
コード(修正前)
public class Warp : MonoBehaviour { private Vector3 target; // ← ワーク void OnTriggerEnter2D (Collider2D other) { target = other.gameObject.transform.position; target.x = warpPoint.x; target.y = warpPoint.y; other.gameObject.transform.position = target; } }
コード(修正後)
public class Warp : MonoBehaviour { private Collider2D target; // ← ワープポイントに衝突したCollider(キャラクター)を保持 private Vector3 v; // ワーク // ワープ処理 void WarpTarget() { v = target.gameObject.transform.position; v.x = warpPoint.x; v.y = warpPoint.y; target.gameObject.transform.position = v; } void OnTriggerEnter2D (Collider2D other) { target = other; WarpTarget(); } }
状態遷移処理の実装
下準備ができたので、いよいよ状態・イベントにフェードイン・アウトとワープ処理を追加します。
コード
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Warp : MonoBehaviour { public Vector2 warpPoint; private Collider2D target; // ← ワープポイントに衝突したCollider(キャラクター)を保持 private Vector3 v; private FadeManager fader; // ワープ中の状態 enum WarpState { Idle, Triggered, FadeOut, FadeIn } private WarpState state; // Start is called before the first frame update void Start() { state = WarpState.Idle; } // ワープ処理 void WarpTarget() { v = target.gameObject.transform.position; v.x = warpPoint.x; v.y = warpPoint.y; target.gameObject.transform.position = v; } // Update is called once per frame void Update() { if( state != WarpState.Idle ){ if( fader.IsFading() == false ){ // 次の処理へ switch( state ){ case WarpState.Triggered: fader.FadeOut(); state = WarpState.FadeOut; break; case WarpState.FadeOut: WarpTarget(); fader.FadeIn(); state = WarpState.FadeIn; break; case WarpState.FadeIn: state = WarpState.Idle; break; default: break; } } } } void OnTriggerEnter2D (Collider2D other) { if( state == WarpState.Idle ) { target = other; state = WarpState.Triggered; } } }
ワープ時に、フェードアウト・インがかかるようになり、いい雰囲気になりました。
エフェクトの着脱
ワープのエフェクトを元に戻すことはさほど大変ではない(コードを戻すだけ)ですが、今後、特定のワープに他のエフェクトを付けたい場合のため、FadeManagerをプログラムの外に出して、付け替えができるようにします。
コード
public class Warp : MonoBehaviour { [SerializeField] FadeManager fader; void OnTriggerEnter2D (Collider2D other) { if( state == WarpState.Idle ) { target = other; if( fader == null ){ WarpTarget(); } else { state = WarpState.Triggered; } } } }
※実際に他のエフェクトを作った場合は、FadeManager は Interface にしないといけないと思いますが、そのうちに考えます。
これからやること
なんかそれっぽくなってきて、心に火がついてきました。ここからはどの順番でやるか選択していく必要があります。まず面白さの追求より基本のエンジンを観察していくので、以下のようにします。(面白さ=ゲームバランスは後から追求します)
(1) 基本:
- ステータス画面(HP、速度だけ)
- 戦闘画面
絶対勝つ戦闘(クリアのデバッグ)
絶対負ける戦闘(ゲームオーバーのデバッグ)
ゲームオーバーの定義
- キャラクターエンカウント(当たり判定の利用)
- ボスエンカウント(当たり判定→戦闘→フラグ設定)
- マルチシーン(タイトル、ゲーム、エンディング)
(2) シナリオの発生:
- イベントフラグ(ダンジョンクエストの解放、ボス戦の解放)
(3) ゲームバランス(駆け引き)の追求:
- ランダムエンカウント
- 会話の発生(当たり判定の利用)
- アイテムの追加―アイテム屋(回復、速度UP、速度DOWN、攻撃UP、攻撃DOWN、効果をはじく)
- 武器の追加(攻撃UP+アイテム効果付与)
- 貨幣の追加
※今回はマップをシングルシーンで作成しましたが、マルチシーンで作成する方法は全部作ってから挑戦します。
- ランダムダメージ
ランダムダメージ
会心の一撃、痛恨の一撃
(4) 長編化
- マルチシーン(シーン間のマップ移動、シーン間のデータ共有)
- ロード・セーブ