【Unity】変数の値を画面上にデバッグ表示できるOSS『Runtime Monitoring』紹介

変数の値を画面上にデバッグ表示できるUnity用OSS『Runtime Monitoring』について紹介します。

Unity 2021.3.0f1
Runtime Monitoring 2.1.4

はじめに

Runtime Monitoringを使うと、変数の値を画面上に簡単にデバッグ表示することができます。

MIT ライセンスで公開されているOSSなので、ライセンスの範囲内で誰でも自由に使用することができます。

インストール方法は以下のリポジトリに書かれていますので、こちらを参照してください。

github.com

アセットストアからもインストールすることもできます。

assetstore.unity.com

本記事ではこのツールの使い方について簡単にまとめます。

基本的な使い方

MonoBehaviourの変数を監視する

MonoBehaviourの持つ変数をモニタリングするには、以下のように MonoBeahaviour.RegisterMonitor() というメソッドを読んだ上で、モニタリングしたい変数に[Monitor] アトリビュートをつけます。

using Baracuda.Monitoring;
using UnityEngine;

public sealed class Example : MonoBehaviour
{
    // モニタリングしたい変数に [Monitor] 属性を付ける
    [Monitor] private int _test;

    private void Awake()
    {
        // このオブジェクトをモニタリング対象とする
        this.RegisterMonitor();
    }

    private void Update()
    {
        _test++;
    }

    private void OnDestroy()
    {
        // このオブジェクトをモニタリング対象から外す
        this.UnregisterMonitor();
    }
}

これを適当なGameObjectにアタッチして再生すると左上に監視対象の値が表示されます。

実行結果

いろんな登録方法

前節ではオブジェクトをモニタリング対象とするために MonoBehaviour.RegisterMonitor() を呼びました。
これは以下のように書くこともできます。

//登録
MonitoringSystems.Resolve<IMonitoringManager>().RegisterTarget(this);

//登録解除
MonitoringSystems.Resolve<IMonitoringManager>().UnregisterTarget(this);

MonoBehaviour の外側から登録を行いたい場合などにはこちらを使います。

また、MonitoredBehaviour を継承したクラスを作成するとこれらの処理を基底クラスで行ってくれます。

using Baracuda.Monitoring;

public sealed class Example : MonitoredBehaviour
{
    // 省略
}

MonitoredBehaviour の他、ScriptableObject 用の MonitoredScriptableObjectC#object 用の MonitoredObject などが用意されています。

モニタリングできるもの

モニタリングできる対象は、フィールド、プロパティ、イベント、メソッドです。

using System;
using Baracuda.Monitoring;

public sealed class Example : MonitoredBehaviour
{
    // フィールド
    [Monitor] private int _testField;
    
    // プロパティ
    [Monitor] private int TestProperty { get; }
    
    // イベント
    [Monitor] private event Action TestEvent;

    // メソッド
    [Monitor]
    private int TestMethod()
    {
        return 0;
    }
}
イベントのモニタリング

前節の方法でイベントをモニタリングすると、下図のように登録されているリスナの情報一覧や、Invoke された数などが一覧表示されます。

イベントのモニタリング

ここまでの情報が不要である場合、以下のように Monitor アトリビュートの代わりに MonitorEvent アトリビュートを使い、引数を指定することで表示情報を制限できます。

// 発火した数とリスナの数だけを表示
[MonitorEvent(EventDisplay.InvokeCount | EventDisplay.SubCount)]
public event Action TestEvent;

実行結果は以下のようになります。

実行結果

メソッドのモニタリング

メソッドについては、 Monitor アトリビュートの代わりに MonitorMethod アトリビュートを使うことで引数を指定できます。

[MonitorMethod(123)]
private int TestMethod(int input)
{
    return input * 100;
}

実行結果は以下の通りです。

メソッドのモニタリング

挙動を変更するためのオプショナルなアトリビュート

出力する文字列をカスタムする MValueProcessor

以下のように MValueProcessor アトリビュートを使用するとモニタリング結果の文字列の出力を方法を変更することができます。

[Monitor] [MValueProcessor(nameof(Process))]
private int _testInt;

private string Process(int input)
{
    return $"出力: {input}";
}

実行結果は以下の通りです。

出力する文字列をカスタム

表示する条件を設定する MShowIf

以下のように MShowIf アトリビュートを使用すると、モニタリング対象の値が条件を満たしていないときは表示を行わず、満たした時のみ表示できます。

//値が100以上の時のみモニタリング結果を表示
[Monitor] [MShowIf(Comparison.Greater, 100)]
private int _testInt;

また、MShowIf の引数にメソッド名や変数の名前を与えると、それが true を返す時のみ表示を行うことができます。

[Monitor] [MShowIf(nameof(IsGreaterThan100))]
private int _testInt;

private bool IsGreaterThan100()
{
    return _testInt > 100;
}
更新タイミングを指定する MUpdateEvent

モニタリング対象の値は、モニタリングを行うために毎フレーム取得されます。
そのため、例えば以下のように transform.position をモニタリングすると、毎フレーム transform へのアクセスが行われることで無駄な処理負荷がかかってしまう可能性があります。

[Monitor]
private Vector3 Position => transform.position;

MUpdateEvent アトリビュートを使うと、引数として指定したイベントが発火した時だけ、モニタリング対象の値を取得して表示を更新します。
つまり以下のように必要な時だけプロパティにアクセスしてモニタリングすることが可能になります。

using System;
using Baracuda.Monitoring;
using UnityEngine;

public sealed class Example : MonitoredBehaviour
{
    [Monitor]
    [MUpdateEvent(nameof(Moved))] // Movedが呼ばれた時のみモニタリングするためにプロパティから値を取得
    private Vector3 Position => transform.position;

    public void Update()
    {
        if (Input.GetKey(KeyCode.Space))
        {
            transform.position += Vector3.forward;
            Moved?.Invoke();
        }
    }

    private event Action Moved;
}

モバイルサポートしてるか?

本ライブラリはREADMEを見る限り、モバイルデバイスでの動作は未検証と書かれています。
そこで検証用のプロジェクトを作成し手元の iOS/Android で動かしてみましたが、問題なく動いていることを確認できました。
プロジェクトの詳細などはツイートからのリンクを参照してください。

その他の機能

本記事では Runtime Monitoring の基本的な使い方だけを紹介しました。
この他にも、モニタリング対象にタグをつけて表示するものをフィルタリングしたり、背景色や文字色・レイアウトなどの装飾を変えるアトリビュートがあったりします。

この辺りは、基本的な使い方に慣れてきたタイミングで README を一読することをお勧めします。

github.com

参考

github.com