LoginSignup
1
0

【Unity】コルーチンとタプルを使って複数のフィールドを監視するメモ

Last updated at Posted at 2023-08-11

やりたいこと

int型のフィールドnum1,num2を監視し、値が更新されたときにstring型のフィールドtextを更新したい。

一般的なやり方

前フレームの値を保持するフィールドを用意し、Update()で判定・更新を行う

public class SampleComponent : MonoBehaviour
{
    // 監視対象
    public int num1;
    public int num2;

    // 変更対象
    public string text;

    // 前フレームの値
    private int prevNum1;
    private int prevNum1;

    // 初期化
    void Start() {
        text = $"{num1}-{num2}";
        prevNum1 = num1;
        prevNum2 = num2;
    }

    void Update() {
        if(num1 != prevNum1 || num2 != prevNum2) {
            text = $"{num1}-{num2}";
            prevNum1 = num1;
            prevNum2 = num2;
        }
    }
}

解説

Update()はフレーム毎に実行されるメソッドです。
prevNum1, prevNum2はそれぞれnum1, num2の前フレームでの値を保持し、それらの値を比較することで値の変更を検知しています。

問題点

  • 監視するフィールド1つごとにフィールドが1つ増える
  • 監視・更新しないといけないフィールドが多くなるとUpdate()が肥大化する

コルーチンを使用した記述方法

public class SampleComponent : MonoBehaviour
{
    // 監視対象
    public int num1;
    public int num2;

    // 変更対象
    public string text;

    void OnEnable() {
        StartCoroutine(CoUpdateText());
    }

    IEnumerator CoUpdateText() {
        while(true) {
            text = $"{num1}-{num2}";
            var state = (num1, num2); // 監視するフィールドの値を1タプルに詰め込む
            yield return new WaitWhile(() => state == (num1, num2));
        }
    }
}

解説

監視・更新処理を全てコルーチン内で完結させるようにしました。
ローカル変数stateは最終更新時点でのフィールドの値を保持しています。
WaitWhileは指定した処理をフレーム毎に実行し、falseを返すまでコルーチンの進行を待機するためのオブジェクトで、ここではstateと現在の値のタプルを比較し、値が変更されるまでコルーチンの進行を待機しています。
WaitWhileを通過した後は、無限ループなので上の更新処理に戻り、再度待機が始まります。

問題点

  • WaitWhileのnewとクロージャのため、フィールドが更新されるたびにヒープアロケーションが発生する

まとめ

肥大化したUpdate()を読み直すのは結構だるい

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0