[Unity][R3]ダメージ処理の呼び出しをStart()で完結させる

2024/03/16に公開

はじめに

R3から使い始めて、UniRxにTriggerという機能があることをはじめて知りました。Triggerを使うと、MonoBehaviourのイベントを変換できます。そうすることで、OnTriggerEnterといった処理をStart()から記述できます。Start()で記述できるメリットとして、処理を追いやすくできます。これにより、ダメージ処理の呼び出しをStart()で完結させることができます。今回は、ダメージを受けると障害物の耐久値が減り、最終的に壁を破壊できる処理を実際に書いていきます。

R3でダメージ処理を実装

R3でダメージ処理を実装したコードが以下になります。

DamageWall.cs
using R3;
using R3.Triggers;
using UnityEngine;
using UnityEngine.UI;

public class DamageWall : MonoBehaviour
{
    [SerializeField] private Text stateText;
    [SerializeField] private int initialhp = 3;
    private ReactiveProperty<int> hp;
    private readonly string playerTag = "Player";

    private void Start()
    {
        hp = new ReactiveProperty<int>(initialhp);

        this.OnCollisionEnterAsObservable()
            .Where(collision => collision.gameObject.CompareTag(playerTag))
            .Subscribe(_ => Damage())
            .AddTo(this);

        hp.Where(x => x <= 0)
            .Subscribe(_ => Break())
            .AddTo(this);

        hp.Subscribe(_ => UpdateStateText())
            .AddTo(this);

        UpdateStateText();
    }

    private void Damage()
    {
        hp.Value--;
    }

    private void Break()
    {
        gameObject.SetActive(false);
    }

    private void UpdateStateText()
    {
        stateText.text = hp.Value <= 0 ? "壁は壊れた" : $"壁の耐久値: {hp.Value}";
    }
}

コード解説

では、上記のコードを詳しくみていきます。

Start()

Startメソッドでは、OnCollisionEnterAsObservableを使って物体の衝突を検知します。つぎに、衝突した相手が、Playerかを検知します。Playerの場合は、Damage()を呼び出します。

Start()
this.OnCollisionEnterAsObservable()
            .Where(collision => collision.gameObject.CompareTag(playerTag))
            .Subscribe(_ => Damage())
            .AddTo(this);

次にhpの処理です。hpが減少したら状態のテキスト(stateText)を変更します。また、hpが0の場合は壁の破壊処理を呼び出します。

Start()
hp.Where(x => x <= 0)
    .Subscribe(_ => Break())
    .AddTo(this);

hp.Subscribe(_ => UpdateStateText())
    .AddTo(this);

Damage()

Damage()ではhpの減少を行います。

Damage()
private void Damage()
{
    hp.Value--;
}

Break()

Break()は、hpが0の時呼び出されます。破壊処理なので、オブジェクトのSetActive()をFalseに変更します。

Break()
private void Break()
{
    gameObject.SetActive(false);
}

UpdateStateText()

hpが変化するごとにUpdateStateText()を呼び出します。この時、hpが0の場合のみ"壁が壊れた"というテキストを表示します。

UpdateStateText()
private void UpdateStateText()
{
    stateText.text = hp.Value <= 0 ? "壁は壊れた" : $"壁の耐久値: {hp.Value}";
}

実際の動作

上記のコードを行うことで、プレイヤーが衝突すると壁の耐久値減り、最終的に破壊される実装を作りました。以下が実際の動作になります。
実際の動作

おわりに

R3でダメージ処理を実装しました。本ブログではUnity中級者向けに、R3を身近な実装で使う方法を紹介しています。この記事が良いと思った人は、いいねとフォローでお願いします。

Discussion