ドキュメント

Unity Engine

Unity Engine

カスタム更新マネージャーの使用

更新マネージャーを作成して、フレームごとの更新を多数処理します。
読み終わるまでの所要時間 9 分最終更新 3日前

Update
、
FixedUpdate
、
LateUpdate
などのUnityのビルトインのフレームごとのイベント機能の更新は、スケールのパフォーマンスに影響を与える可能性があります。対応するコールバックは C# MonoBehaviour スクリプトで呼び出されますが、機能呼び出しは Unity のネイティブコードから発生します。Unity は、これらの更新関数をコールするオブジェクトを追跡するための内部リストを保持する必要があります。MonoBehaviour スクリプト インスタンスは、有効または無効にしたときに、これらのリストに追加またはリストから削除されます。
適切なコールバックを必要とするプロジェクト内のすべての MonoBehaviour インスタンスに適切なコールバックを追加するのは便利ですが、コールバックの数が増えると非効率的になります。ネイティブコードからマネージコードコールバックを呼び出すと、小さいながらも重大なオーバーヘッドが発生します。これは、以下の結果につながります。
  • 大量の
    Update
    コールバックを呼び出すときのフレーム時間が低下します。
  • プレハブ内の各コンポーネントで
    Awake
    コールバックと
    OnEnable
    コールバックを呼び出すことによるパフォーマンスのオーバーヘッドが原因で、多数の MonoBehaviour を含むプレハブをインスタンス化するときに、インスタンス化時間が低下しました。
これらの問題を回避するには、ビルトインコールバックに依存する代わりに、グローバルカスタム更新マネージャのシングルトンインスタンスを作成し、MonoBehaviour スクリプトまたは標準の C# オブジェクトにサブスクライブさせます。このようにすると、更新マネージャーシングルトンは、
Update
、
LateUpdate
、およびその他のコールバックを、それらにサブスクライブしているすべてのオブジェクトに分散することができ、すべての更新コードはマネージレイヤーに留まります。これには、実行する操作がないときに、コードがコールバックからサブスクライブ解除できるようになるため、各フレームで呼び出す必要がある関数の数が減るという利点もあります。

カスタム更新マネージャを使用する場合

カスタム更新マネージャーは、フレームごとの更新コールバックを持つ MonoBehaviour インスタンスの数が数百または数千に達したときに便利です。
実行頻度の低いコールバックを排除することで、パフォーマンスを大幅に向上させることができます。以下の例を考えてみましょう。
void Update() { if(!someVeryRareCondition) { return; }// … some operation …}
プロジェクトにこのような
Update
コールバックを持つ MonoBehaviour が多数ある場合、
Update
コールバックの実行に消費される時間のかなりの部分が、MonoBehaviour 実行のネイティブコードドメインとマネージコードドメインの切り替えに費やされ、その後すぐに終了します。これらのクラスが、
someVeryRareCondition
が true の間だけグローバル更新マネージャーにサブスクライブし、その後はサブスクライブ解除すると、コードドメインの切り替えとまれな状態の評価の両方に費やす時間が短縮されます。
重要
カスタム更新マネージャは、1 つのサイズですべてに対応するソリューションではありません。プロジェクトを プロファイル して、特定のパフォーマンスの問題とカスタム更新マネージャが適切かどうかを判断することが重要です。プロジェクト内の特定のパフォーマンスボトルネックに応じて、パフォーマンスを最適化する他の方法として、プロジェクトを ECS (エンティティコンポーネントシステム) アーキテクチャを使用するように変更したり、プレイヤーループのカスタマイズ を行う方法があります。

カスタム更新マネージャの例

カスタム更新マネージャーを実装するには、最初に Cスクリプトを作成し、以下のようにインターフェースフェースを定義します。
public interface IUpdatable{ void CustomUpdate(float deltaTime);}
次に、更新マネージャーシングルトン用の MonoBehaviour スクリプトを作成できます。更新マネージャーはビルトインの
Update
コールバックを実装します。その後、他の MonoBehaviour スクリプトコンポーネントは、この更新マネージャーに直接
Update
するのではなく、この更新マネージャーにサブスクライブできます。
// Singleton update manager. Attach to a GameObject in your scene.using System.Collections.Generic;using UnityEngine;public class UpdateManager :MonoBehaviour{ private 静的 UpdateManager _instance; public static UpdateManager Instance => _instance; private readonly リスト<IUpdatable> updatables = new リスト<IUpdatable>(); void Awake() { if (_instance == null) _instance = this; else Destroy(gameObject); } public void Register(IUpdatable updatable) { if (!updatables.Contains(updatable)) updatables.Add(updatable); } public void Unregister(IUpdatable updatable) { updatables.Remove(updatable); } void Update() { float deltaTime = Time.deltaTime; // Optionally: for performance, iterate backwards if you allow removal during iteration Foreach (更新可能な変数) { updatable.CustomUpdate(deltaTime); } }}
最後に、MonoBehaviour スクリプトコンポーネントを作成し、enable 時に更新マネージャーインスタンスに登録し、使用不可 時に登録解除します。以下の例では、カスタム更新コールバックを使用して親ゲームオブジェクトを移動しています。
// Script component. Attach to a GameObject in your scene to move it on each custom update.using UnityEngine;public class MyMovingObject :MonoBehaviour、IUpdatable{ void OnEnable() { UpdateManager.Instance.Register(this); } void OnDisable() { if (UpdateManager.Instance != null) UpdateManager.Instance.Unregister(this); } public void CustomUpdate(float deltaTime) { // Your update logic here transform.position += Vector3.right * deltaTime; }}

追加リソース