ClientNetworkTransform を用いて Client 側で Transform の同期処理を行う【Netcode for GameObjects】

問題提起

github.com

NetworkTransform は NetworkVariable を用いて Transform の同期を行っています.
ここで思い出して頂きたいのですが,NGO 版から NetworkVariable の値設定は Server の権限でしかできなくなったため,
例えば Client 側の Input で NetworkObject の Transform を更新しようとして, これまでの MLAPI と同様に,NetworkTransform をアタッチしても Transform の同期はできなくなりました.
というより,移動自体ができません(移動しようとしても瞬時にスポーン時の Transform に戻る)

ClientNetworkTransform

とはいえ,NetworkTransform のコードを読んでみると,以下の記載があります.

        /// <summary>
        /// Tries updating the server authoritative transform, only if allowed.
        /// If this called server side, this will commit directly.
        /// If no update is needed, nothing will be sent. This method should still be called every update, it'll self manage when it should and shouldn't send
        /// </summary>
        /// <param name="transformToCommit"></param>
        /// <param name="dirtyTime"></param>
        protected void TryCommitTransformToServer(Transform transformToCommit, double dirtyTime)
        {
            var isDirty = ApplyTransformToNetworkState(ref m_LocalAuthoritativeNetworkState, dirtyTime, transformToCommit);
            TryCommit(isDirty);
        }

つまり,NetworkTransformを基底とし,Client 側で Transform の更新が行えるような拡張クラスを作ればよさそうです.
実は Package Manager に載っているサンプルで ClientNetworkTransform があるんですよね.

using Unity.Netcode.Components;
using UnityEngine;

namespace Unity.Netcode.Samples
{
    /// <summary>
    /// Used for syncing a transform with client side changes. This includes host. Pure server as owner isn't supported by this. Please use NetworkTransform
    /// for transforms that'll always be owned by the server.
    /// </summary>
    [DisallowMultipleComponent]
    public class ClientNetworkTransform : NetworkTransform
    {
        /// <summary>
        /// Used to determine who can write to this transform. Owner client only.
        /// Changing this value alone will not allow you to create a NetworkTransform which can be written to by clients.
        /// We're using RPCs to send updated values from client to server. Netcode doesn't support client side network variable writing.
        /// This imposes state to the server. This is putting trust on your clients. Make sure no security-sensitive features use this transform.
        /// </summary>
        // This is public to make sure that users don't depend on this IsClient && IsOwner check in their code. If this logic changes in the future, we can make it invisible here

        public override void OnNetworkSpawn()
        {
            base.OnNetworkSpawn();
            CanCommitToTransform = IsOwner;
        }

        protected override void Update()
        {
            base.Update();
            if (NetworkManager.Singleton != null && (NetworkManager.Singleton.IsConnectedClient || NetworkManager.Singleton.IsListening))
            {
                if (CanCommitToTransform)
                {
                    TryCommitTransformToServer(transform, NetworkManager.LocalTime.Time);
                }
            }
        }
    }
}

Client 側で NetworkObject の Transform を更新したい場合は ClientNetworkTransform を利用しましょう.

github.com

終わりに

Inspector 側で CanCommitToTransform が露出されていますが,
Unity Editor でここはチェックを入れないようにしてください.
現時点ではバグって永久にワーニングのログが出るようになってしまいます.