スーパーアーマーの実装メモ【Unity】

f:id:coffee_ryo:20180730165929g:plain

仕様
  • 対象はキャラクター
  • オブジェクト衝突時にダメージを受ける
  • 一度ダメージを受けるとしばらくスーパーアーマー状態
  • スーパーアーマー中はダメージを受けない
  • 時間の経過でスーパーアーマーは解除される
  • スーパーアーマー中キャラを点滅
Unityバージョン

2018.1.0f2 Personal ※UniRx使う

クラス図

f:id:coffee_ryo:20180730152655p:plain

  • ReactivePropertyを使って、スーパーアーマーである時間を設定
  • ダメージを与えるコンポーネントで、スーパーアーマー残り時間が0よりも大きければ攻撃しない
  • スーパーアーマー中は、rendererコンポーネントのenableの値を1フレーム置きに更新する
ダメージ処理のフローチャート

f:id:coffee_ryo:20180730165354p:plain

コード

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;
    }
}
完成したもの

f:id:coffee_ryo:20180730165929g:plain

未検証事項
  • rendererのenableを切り替えて点滅させるのではなく、シェーダーを使って点滅させた方が実行速度でる?