[Unity3D]UPDATE()は遅いらしいし

  • UPDATE()を10000回呼ぶ
    Unityのオフィシャルブログの記事を見ていくつか気づいたこと、今後すべきことをメモしておく。

気づいたこと

  • Script Call Optimization を Fast but no Exceptions に変更 という作業で高速化できる
  • Updateは遅い

Script Call Optimization を Fast but no Exceptions に変更

Updateをまま使う場合、 Script call optimazation の項目を設定してあげる必要がある。

メニュー: Edit->Project Settings->Player

ここから設定が可能。

Updateは遅い

Updateやその他のマジックメソッドは、まずUnity側に登録されてその後GameObjectの存在チェックやNullチェック等を経て初めて呼び出される。
そのため、たとえ中身がカラだとしても void Update(){} と記述するだけで呼び出し対象にはなるし、上記のチェック等を経ているために処理の対象になり、少ないとはいえレイテンシーが発生する。

記事中では、この辺が必要無い場合、自前でManagerを作ってManagerのUpdate時に子に対して自前のUpdateを流す仕組みの方が高速であるとしている。
さらにListではなくArrayを使用したほうが効率的だとも述べられている。

自律制御のテストをしやすく子として呼ばれた時もよ動作させやすいやりかた

Manager側は一方的に呼び出すで良いとして、子側はMonobehaviour継承クラスだとしても void Update() 等を記述しない
自律テストをする場合は ChildDriver としてUpdate内で自身に着いた子用コンポーネントを自動取得して自前Updateを呼び出す仕組みにしてテストしたら良いと思われる。

具体的には

マネージャとして以下の様なコンポーネントでUpdate呼び出し。ブログまま。

    public abstract class Manager<ChildType> : MonoBehaviour
        where ChildType : IManagedMember
    {
        protected ChildType[] members;
        protected void Update(){
            int count = members.Length;
            for (var i = 0; i < count; i++) members[i].UnmmanagedUpdate();
        }
    }

呼び出される側はこんな感じでインターフェースを用意。

    public interface IManagedMember{
        void UnmmanagedUpdate();
    }
    public abstract class ManagedMember : MonoBehaviour,IManagedMember {
        public abstract void UnmmanagedUpdate();
    }

独立して子の挙動をテストしたいこ時は子にこれを追加してあげる。

    public class ManagedMemberDriver : MonoBehaviour {
        IManagedMember[] components;
        void Start () {
           this.components = GetComponents<IManagedMember>();
        }
        void Update () {
            int count = components.Length;
            for (var i = 0; i < count; i++) components[i].UnmmanagedUpdate();
        }
    }

あとは必要に応じてManager側には子作りメソッドを用意したりで色々できる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です