Network Update Loop で MonoBehaviour ライフサイクル前後に処理を差し込む【MLAPI】

MLAPI v0.1.0 から Network Update Loop という MonoBehaviour のライフサイクルの前後に処理を差し込める機能が追加されました.

Network Update Loop

RPC queue,Transport の IO 関連の処理を MonoBehaviour のライフサイクル外で処理を走らせたい場合があり,
それを解決するための MLAPI 独自のライフサイクルイベントを構築するインフラシステムです.

Player Loop System

こう言ったシステムを作る時に Player Loop System を利用しているようです.

docs.unity3d.com

ちなみに Player Loop System は VContainer でも利用されていますね.

vcontainer.hadashikick.jp

つまり,Player Loop System を理解していれば,MLAPI の NetworkUpdateLoop の実装方法は,
VContainer に似通った形になるのは予想がつきます.

tsubakit1.hateblo.jp

Update Stage

以下の画像の通りに呼ばれます.

f:id:xrdnk:20210401224119p:plain

もう少しシーケンスの中身を深く追いたい場合はこちらのサイトをご覧ください.

docs-multiplayer.unity3d.com

基本的に Network Update Loop は MonoBehaviour ライフサイクルより前に呼ばれるようです.
e.g. NetworkUpdateLoop.FixedUpdate → MonoBehaviour.FixedUpdate,NetworkUpdateLoop.Update → MonoBehaviour.Update

椿さんのこちらの記事を参考に各 Update Stage に盛り込む処理をば.

tsubakit1.hateblo.jp

Update Stage 内容
Initialization 「時間」のアップデートやステートの同期など
EarlyUpdate 「入力」の更新
FixedUpdate 物理演算系
PreUpdate 物理演算の反映・マウス入力云々
Update アップデート処理
PreLateUpdate アニメーションの更新
PostLateUpdate 布の更新とかレンダリング

How To Use

サンプルスクリプトを載せます.

using MLAPI;
using UnityEngine;

namespace MLAPIPractice
{
    // Network Update Loop を利用する場合は INetworkUpdateSystem を実装する
    public class NetworkUpdateSystemTest : NetworkBehaviour, INetworkUpdateSystem
    {
        private void OnEnable()
        {
            // Update Stages の順番は以下の通り.
            // 追加したい Stage を指定する時は this.RegisterNetworkUpdate() を最初に指定する
            this.RegisterNetworkUpdate(NetworkUpdateStage.Initialization);
            // ちなみに上のコードはこちらと同じ
            // NetworkUpdateLoop.RegisterNetworkUpdate(this, NetworkUpdateStage.Initialization);

            this.RegisterNetworkUpdate(NetworkUpdateStage.EarlyUpdate);
            this.RegisterNetworkUpdate(NetworkUpdateStage.FixedUpdate);
            this.RegisterNetworkUpdate(NetworkUpdateStage.PreUpdate);
            this.RegisterNetworkUpdate(NetworkUpdateStage.Update); // 引数なしでも同様
            this.RegisterNetworkUpdate(NetworkUpdateStage.PreLateUpdate);
            this.RegisterNetworkUpdate(NetworkUpdateStage.PostLateUpdate);

            // 全ての Update States を指定したい場合は以下で宣言してもよい
            // this.RegisterAllNetworkUpdates();
            // こちらでもよい
            // NetworkUpdateLoop.RegisterAllNetworkUpdates(this);
        }

        /// <summary>
        /// RegisterNetworkUpdate に指定した Stages が Resolve される
        /// </summary>
        /// <param name="updateStage">updateStage</param>
        public void NetworkUpdate(NetworkUpdateStage updateStage)
        {
            Debug.Log($"{nameof(NetworkUpdateSystemTest)}.{nameof(NetworkUpdate)}({updateStage})");
        }
        
        private void Update()
        {
            Debug.Log($"{nameof(NetworkUpdateSystemTest)}.{nameof(Update)}()");
        }
        
        private void FixedUpdate()
        {
            Debug.Log($"{nameof(NetworkUpdateSystemTest)}.{nameof(FixedUpdate)}()");
        }

        private void LateUpdate()
        {
            Debug.Log($"{nameof(NetworkUpdateSystemTest)}.{nameof(LateUpdate)}()");
        }

        private void OnDisable()
        {
            // Dispose する時は以下のように宣言する
            this.UnregisterAllNetworkUpdates();
            // こちらでもよい
            // NetworkUpdateLoop.UnregisterAllNetworkUpdates(this);
        }
    }
}

INetworkUpdateSystem を実装し,MonoBehaviour の前後に差し込みたい処理を NetworkUpdate の中に書きます.
どのタイミングで差し込みたいかは,初期化処理段階で Register し,使わなくなったら Unregister する流れになります.
NetworkUpdateStage を Register することで NetworkUpdate メソッドに Inject されます.

Register の書き方は二通りあり,以下のようになります.下の方だとRiderちゃんに上の方がイイヨ~って下線がつくけど.

            // 追加したい Stage を指定する時は this.RegisterNetworkUpdate() を最初に指定する
            this.RegisterNetworkUpdate(NetworkUpdateStage.Initialization);
            // ちなみに上のコードはこちらと同じ
            // NetworkUpdateLoop.RegisterNetworkUpdate(this, NetworkUpdateStage.Initialization);

引数なしの場合は,Updateが登録されるようです.
Unregister する時は Register を Unregister に変えるだけでOK.

まあ少し軽く動作確認しますか.

gyazo.com

使いどころはしっかり考えて実装する感じになりそうです.

Reference

docs-multiplayer.unity3d.com

docs-multiplayer.unity3d.com

docs.unity3d.com