Moving platform client desync

I have created a vertical moving platform which on a players personal screen is perfectly synced, no jittering and you keep your velocity. However for any other player when watching someone on the elevator, the player is sinking through the floor a little when going upwards and hovering when going downward. Any idea how to fix this? Ive tried the platform as a rigid body which made it 10x worse, ive used a client network transform as well as a network transform. My players use client network transforms and are controlled by character controllers.

using UnityEngine;
using Unity.Netcode;
using System.Collections.Generic;

public class VerticalPlatform : NetworkBehaviour
{
    #region Variables
    [Header("Settings")]
    [SerializeField] private float m_speed;
    [SerializeField] private Vector3 m_startPosition;
    [SerializeField] private Vector3 m_endPosition;

    private float m_direction;
    private Dictionary<ulong, NetworkObject> m_playersOnPlatform = new Dictionary<ulong, NetworkObject>();
    #endregion

    #region Mono
    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.T))
        {
            m_direction = 1.0f;
        }

        if(Input.GetKeyDown(KeyCode.Y))
        {
            m_direction = -1.0f;
        }
    }

    private void FixedUpdate()
    {
        if(m_direction == 0.0f) return;

        if(IsServer)
        {
            // Move the platform
            if (m_direction == 1.0f) MoveUp();
            if (m_direction == -1.0f) MoveDown();
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        // Check if collider belongs to a player
        var obj = other.GetComponent<NetworkObject>();
        if(obj != null && obj.GetComponent<PlayerMovement>() != null)
        {
            // Try set parent
            obj.TrySetParent(transform, true);

            // Ensure player is snapped to the platform's position on parenting
            var relativePosition = transform.InverseTransformPoint(obj.transform.position);
            obj.transform.position = transform.TransformPoint(relativePosition);

            // Add to dictionary
            m_playersOnPlatform.Add(obj.OwnerClientId, obj);
        }
    }

    private void OnTriggerExit(Collider other)
    {
        // Check if collider belongs to a player
        var obj = other.GetComponent<NetworkObject>();
        if(obj != null && obj.GetComponent<PlayerMovement>() != null)
        {
            // Check if players on platform
            if(m_playersOnPlatform.ContainsKey(obj.OwnerClientId))
            {
                // Try remove parent
                m_playersOnPlatform[obj.OwnerClientId].TryRemoveParent(true);

                            // Ensure player is snapped to the platform's position on parenting
            var relativePosition = transform.InverseTransformPoint(obj.transform.position);
            obj.transform.position = transform.TransformPoint(relativePosition);

                // Remove from dictionary
                m_playersOnPlatform.Remove(obj.OwnerClientId);
            }
        }
    }
    #endregion

    #region Platform
    private void MoveUp()
    {
        // Increase y value
        var newPos = transform.position;
        newPos.y += m_speed * Time.fixedDeltaTime;

        // Update transform
        transform.position = newPos;

        // Check if y value has reached target
        if(transform.position.y >= m_endPosition.y)
        {
            // Set to target
            transform.position = m_endPosition;

            // Clear direction
            m_direction = 0.0f;
        }

        UpdatePositionClientRPC(transform.position);
    }

    private void MoveDown()
    {
        // Decrease y value
        var newPos = transform.position;
        newPos.y -= m_speed * Time.fixedDeltaTime;

        // Update transform
        transform.position = newPos;

        // Check if y value has reached target
        if(transform.position.y <= m_startPosition.y)
        {
            // Set to target
            transform.position = m_startPosition;

            // Clear direction
            m_direction = 0.0f;
        }

        UpdatePositionClientRPC(transform.position);
    }

    [ClientRpc]
    private void UpdatePositionClientRPC(Vector3 newPosition)
    {
        if(IsServer) return;

        transform.position = newPosition;
    }
    #endregion
}
using Unity.Netcode;
using UnityEngine;

public class PlayerMovement : NetworkBehaviour
{
    #region Variables
    [Header("Camera")]
    [SerializeField] private Transform m_camera;
    [SerializeField] private float m_sensitivity;

    [Header("Movement")]
    [SerializeField] private float m_walkSpeed;
    [SerializeField] private float m_jumpHeight;
    private bool m_isGrounded;

    private CharacterController m_controller;
    #endregion

    #region Mono
    private void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
    }

    private void Update()
    {
        if(IsOwner)
        {
            m_isGrounded = m_controller.isGrounded;

            HandleCameraInput();
            HandleMoveInput();
        }
    }
    #endregion

    #region Network
    public override void OnNetworkSpawn()
    {
        // Owner only
        if(IsOwner)
        {
            m_controller = GetComponent<CharacterController>();
        }
    }
    #endregion

    #region Camera
    private void HandleCameraInput()
    {
        // Get raw input
        var input = PlayerInput.Instance.GetRawCameraInput() * m_sensitivity;

        // Rotate camera (up and down)
        m_camera.localRotation = Quaternion.Euler(new Vector3(input.y, 0.0f, 0.0f));;

        // Rotate body (left and right)
        transform.rotation *= Quaternion.Euler(new Vector3(0.0f, input.x, 0.0f));
    }
    #endregion

    #region Motor
    private void HandleMoveInput()
    {
        // Handle jump input
        HandleJumpInput();

        // Get raw input
        var input = PlayerInput.Instance.GetRawMoveInput();
        input.x *= m_walkSpeed;
        input.y *= Time.deltaTime;
        input.z *= m_walkSpeed;

        // Apply movement
        m_controller.Move(transform.TransformDirection(input));
    }

    private void HandleJumpInput()
    {
        // Get jump input
        if(Input.GetKeyDown(KeyCode.Space) && m_isGrounded)
        {
            PlayerInput.Instance.SetVelocity(PlayerInput.Instance.GetVelocity() + Mathf.Sqrt(m_jumpHeight * -2.0f * Physics.gravity.y));
        }

        // Add gravity
        if(!m_isGrounded)
        {
            PlayerInput.Instance.SetVelocity(PlayerInput.Instance.GetVelocity() + Physics.gravity.y * Time.deltaTime);
        }

        // Reset velocity
        if(m_isGrounded && PlayerInput.Instance.GetVelocity() < 0.0f)
        {
            PlayerInput.Instance.SetVelocity(-2.0f);
        }
    }
    #endregion
}
Netcode Moving Platform Desync

@iiProLivo
You might take a look at this example of handling platforms and non-rigidbody character controllers here.

It does use NGO v2 which requires Unity 6, but there are some additional feature sets used from NGO v2 that allows for smooth parenting transitions and keeping the character controller in synch with the platform (specific to the issue you are describing).

There is a moving platform that has the motion of an elevator in the example and I think it should provide you with a good starting point.

Let me know if this helps?