スーパーアーマーの実装メモ【Unity】
仕様
- 対象はキャラクター
- オブジェクト衝突時にダメージを受ける
- 一度ダメージを受けるとしばらくスーパーアーマー状態
- スーパーアーマー中はダメージを受けない
- 時間の経過でスーパーアーマーは解除される
- スーパーアーマー中キャラを点滅
Unityバージョン
2018.1.0f2 Personal ※UniRx使う
クラス図
- ReactivePropertyを使って、スーパーアーマーである時間を設定
- ダメージを与えるコンポーネントで、スーパーアーマー残り時間が0よりも大きければ攻撃しない
- スーパーアーマー中は、rendererコンポーネントのenableの値を1フレーム置きに更新する
ダメージ処理のフローチャート
コード
IStatus ステータスのinterface ※ここinterfaceにしておけば、ダメージ処理が簡潔に書けると思ってる
using UniRx; public interface IStatus{ ReactiveProperty<float> TimeSuperArmor{get; set;} }
PlayerStatus ステータスの実装 キャラクターオブジェクトにアタッチする
using UnityEngine; using UniRx; public class PlayerStatus : MonoBehaviour , IStatus{ public ReactiveProperty<float> TimeSuperArmor{get; set;} void Awake (){ TimeSuperArmor = new ReactiveProperty<float>(); } }
SuperArmorTimeUpdater 経過時間をinputとして、スーパーアーマーの残り時間を減らしていく キャラクターオブジェクトにアタッチする
using UnityEngine; using UniRx; using UniRx.Triggers; public class SuperArmorTimeUpdater : MonoBehaviour { IStatus status; void Start () { status = this.GetComponent<IStatus>(); this.UpdateAsObservable() .Where(x => status.TimeSuperArmor.Value > 0) .Subscribe(x => { status.TimeSuperArmor.Value -= Time.deltaTime; }); } }
SuperArmorBlinker スーパーアーマー中にレンダラー(キャラクター画像に当たる)を点滅させる キャラクターオブジェクトにアタッチする
using UnityEngine; using UniRx; using UniRx.Triggers; public class SuperArmorBlinker : MonoBehaviour { IStatus status; SpriteRenderer renderer; void Start () { status = this.GetComponent<IStatus>(); renderer = this.GetComponent<SpriteRenderer>(); this.UpdateAsObservable() .Where(x => status.TimeSuperArmor.Value > 0) .Subscribe(x => { renderer.enabled = this.BoolSwitch(renderer.enabled); }); // スーパーアーマーが終わったら、レンダラーを必ず有効にしてあげる status.TimeSuperArmor .Where(time => time <= 0) .Subscribe(time => { renderer.enabled = true; }); } bool BoolSwitch(bool flg){ if(flg == true){ return false; }else{ return true; } } }
Damager ダメージを与えるコンポーネント なんらかの攻撃を行うオブジェクトにアタッチする
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Damager : MonoBehaviour { void OnTriggerEnter2D(Collider2D collider) { // ステータスコンポーネントを取得 var status = collider.gameObject.GetComponent<IStatus>(); // コンポーネントがなければ、ダメージを与えられないオブジェクトとして処理終わり if(status == null){ Debug.Log("ステータスコンポーネントを持っていないオブジェクトと衝突"); return; } // スーパーアーマー中であればダメージを与えない if(status.TimeSuperArmor.Value > 0){ Debug.Log("スーパーアーマー中"); return; } // ここにダメージ処理記述 Debug.Log("ダメージを与えた!!"); // スーパーアーマー状態にする(動作確認用に2.0fにしてます) status.TimeSuperArmor.Value = 2.0f; } }
完成したもの
未検証事項
- rendererのenableを切り替えて点滅させるのではなく、シェーダーを使って点滅させた方が実行速度でる?