はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】Unity2020.1からの新機能Profiling CoreでProfilerに独自のカウンターを追加する(ProfilerCounter, ProfilerCounterValue)

はじめに

今回はUnity2020.1からの新機能であるProfiling Coreを利用して、Profilerに独自のカウンターを追加してみたいと思います。

またビルドしたときにパフォーマンスに影響がでてしまうのでは…とお考えの奥様、そこはしっかりとビルド時にコンパイルされないようになっているのでご安心を。

Both ProfilerCounter and ProfilerCounterValue are compiled out in non-development builds.

Profiler counters API guide | Unity Profiling Core API | 1.0.0

Does nothing in Release Players.

Struct ProfilerCounter<T> | Unity Profiling Core API | 1.0.0

f:id:hanaaaaaachiru:20210923164118p:plain
動作している様子

動作環境

Unity2020.3.18f1

導入方法

まずはPackage Managerを開きます。

f:id:hanaaaaaachiru:20210922095551p:plain
PackageManagerの開き方

利用するパッケージはUnity Profiling Core APIで、現段階ではPreviewです。ですのでGitからインストールする必要があります。

左上に表示されている+ボタンをクリックし、Add package from git URL....を選択、com.unity.profiling.coreと入力してください。

f:id:hanaaaaaachiru:20210922100518p:plain
Add package from git URL
f:id:hanaaaaaachiru:20210922100531p:plain
com.unity.profilling.coreと入力

するとダウンロードが開始されるので、少し待って以下の画面が出れば完了です。

f:id:hanaaaaaachiru:20210923153025p:plain
Unity Profiling Core APIをインストール

コード

Profilerに独自のカウンターを追加するためにはProfilerCounterもしくはProfilerCounterValueを利用します。
Struct ProfilerCounter<T> | Unity Profiling Core API | 1.0.0
Struct ProfilerCounterValue<T> | Unity Profiling Core API | 1.0.0

public class ProfilingTest : MonoBehaviour
{
    // ProfilerCounterはSampleメソッドが呼ばれるたびにプロファイラの値を更新する
    private static readonly ProfilerCounter<int> PlayerCount =
        new ProfilerCounter<int>(category: ProfilerCategory.Scripts, name: "プレイヤーの数", dataUnit: ProfilerMarkerDataUnit.Count);

    // staticでなくてもちゃんと動作します
    private ProfilerCounter<int> EnemyCount;
    
    // ProfilerCounterValueはCPUフレームの最後に自動で値を更新してくれる(一応Sampleメソッドもある)
    private static readonly ProfilerCounterValue<int> BulletCount = new ProfilerCounterValue<int>(category: ProfilerCategory.Scripts, name: "弾の数", dataUnit: ProfilerMarkerDataUnit.Count);

    private int _playerCount;
    private int _enemyCount;

    private void Awake()
    {
        // ゲームオブジェクトの名前をプロファイラーに表示してみたりもできる
        EnemyCount = new ProfilerCounter<int>(ProfilerCategory.Scripts, $"{gameObject.name} : 敵の数", ProfilerMarkerDataUnit.Count);
    }

    private void Update()
    {
        _playerCount += Random.Range(0, 4);
        _enemyCount += Random.Range(0, 10);

        BulletCount.Value += Random.Range(0, 100);
        
        // プロファイルに表示されている値を更新する
        PlayerCount.Sample(_playerCount);
        EnemyCount.Sample(_enemyCount);
    }
}

ProfilerCounterProfilerCounterValueはともにコンストラクタの引数に以下をとります。

名前 意味
category カテゴリー
name カウンターの名前
dataUnit ユニットタイプの値

コメントでも書きましたが、ProfilerCounterProfilerCounterValueの違いは値の更新の仕方にあります。

名前 値の更新
ProfilerCounter Sampleメソッドを呼ぶと更新してくれる
ProfilerCounterValue CPUフレームの最後に自動で更新してくれる(Sampleメソッドも一応あり)

基本的に値を頻繁に変更するときはProfilerCounterValue、そうでもないならProfilerCounterを利用すると良いでしょう。

またジェネリックの<T>にはintuintlongulongfloatdoubleに対応しています。

Profilerに追加する

コードが書き終わったら、Profilerにて一操作が必要です。

メニューバーからWindow -> Analysis -> Profilerを選択して、Profilerを開いた後、左上のProfiler Moduleを選択し、左下の歯車マークを選択。

f:id:hanaaaaaachiru:20210923160502p:plain
Profiler Module

するとProfiler Module Editorが開くので、左下のAddを選択してModuleを新規作成。

f:id:hanaaaaaachiru:20210923160925p:plain
Profiler Module Editor

あとはモジュールの名前を書き換えたり、Available Countersの中から追加したものを選択・Add Selectedを押して追加してください。

f:id:hanaaaaaachiru:20210923161348p:plain
追加する様子

編集が終わったら右下のsave changesを押せば設定完了です。

最後にProfilerProfiler Modulesを選択、自身が作成したモジュールにチェックを入れればOKです。

f:id:hanaaaaaachiru:20210923161605p:plain
作成したモジュールにチェックを入れる
f:id:hanaaaaaachiru:20210923162338p:plain
動作している様子

さいごに

ドキュメントのサンプルではstaticで定義していましたが、別にstaticでなくてもOKでしっかりと反映されていました。

また実機でも動作するか試してみたところ(実機のProfilerをUnityEditorで確認できる機能がある)、ちゃんと動作するようです。

これを応用すると特定の処理の負荷を調べたり、何かの特定の値の増減・ピークを調べたりと色々とProfilingの幅が広がると思います。

是非うまく活用してみてください。

ではまた。