Player Movement Lag

When I test my game without relay , character movements work properly, but when test with relay, other players character movements do not work properly. What is the reason?

this is my movement code

using System.Collections;
using UnityEngine;
using TMPro;
using Random = UnityEngine.Random;
using Unity.Netcode;
using UnityEngine.SceneManagement;

public class Movement : NetworkBehaviour
{
    private Rigidbody2D rb;
    private Animator anim;
    [SerializeField] private float Speed;
    [SerializeField] private float JumpForce;
    [SerializeField] private bool Ice;
    private float move;

    private enum MovementState { idle, runing, falling, jumping, Death}

    [SerializeField] private LayerMask JumpableGround;

    public bool CanMove = false;
    public bool CanTakeDamage = false;

    private NetworkVariable<Vector2> NewVelocity = new NetworkVariable<Vector2>();

    private void Start()
    {
        anim = GetComponent<Animator>();
        rb = GetComponent<Rigidbody2D>();
        NewVelocity.Value = rb.velocity;
        CanMove = true;
        CanTakeDamage = true;
    }
    private void Update()
    {
        if (IsOwner)
        {   
            if (CanMove)
            {
                move = Input.GetAxisRaw("Horizontal");

                if (Ice)
                    rb.AddForce(new Vector2(move * Speed, rb.velocity.y));
                else
                    rb.velocity = new Vector2(move * Speed, rb.velocity.y);

                if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.W))
                {
                    if (IsGrounded())
                    {
                        if (Ice)
                            rb.velocity = new Vector2(rb.velocity.x, JumpForce / 2);
                        else
                            rb.velocity = new Vector2(rb.velocity.x, JumpForce);
                    }
                }
                UpdatePositionServerRpc(rb.velocity);
            }
        }
        else
        {
            rb.velocity = NewVelocity.Value;
        }
        UpdateAnim();
    }

   [ServerRpc]
    private void UpdatePositionServerRpc(Vector2 newValue)
    {
        NewVelocity.Value = newValue;
    }

 private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("ice"))
        {
            Ice = true;
        }
    }
    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("ice"))
        {
            Ice = false;
        }
    }
    private bool IsGrounded()
    {   
        return Physics2D.BoxCast(coll.bounds.center, coll.bounds.size, 0f, Vector2.down, 0.05f, JumpableGround);
    }
    private void UpdateAnim()
    {
        if(CanMove)
        {
            MovementState state;
            if (rb.velocity.x > 0.1f)
            {
                state = MovementState.runing;
                sprite.flipX = false;
            }
            else if (rb.velocity.x < -0.1f)
            {
                state = MovementState.runing;
                sprite.flipX = true;
            }
            else
            {
                state = MovementState.idle;
            }

            if (rb.velocity.y > 0.1f)
            {
                state = MovementState.jumping;
            }
            else if (rb.velocity.y < -0.1f)
            {
                state = MovementState.falling;
            }
            anim.SetInteger("State", (int)state);
        }
    }
}

You are probably connecting them directly within your local network, which means barely any latency. When you use Relay all traffic goes to some server somewhere nearby and returns, which means standard Internet latency.

Since you use a non-kinematic Rigidbody (I see you applying forces) over the network this is not going to go smoothly (or without really weird behaviour) either way. Networked games very rarely use non-kinematic physics bodies for their player characters.

And when they do, as in Rocket League, they write their own deterministic physics engine and spend a lot of time optimizing the heck out of it since it has to run at 120 Hz to feel smooth (for a fast, competitive game).

Thank you for helping me. Do you mean that I should do the character movement without using Rigidbody?

With Rigidbody but set to Kinematic. Or without.

Better yet: use one of the existing character controllers. You don’t want to re-invent the wheel. And definitely no camera scripting - for this you have Cinemachine with built-in, configurable first and third person, top-down, orbit, etc. camera behaviours.

how to move character using rigidbody2d kinematic
? When I use kinematic, the character cannot use gravity, and when I test it using kinematic, it still moves with a delay. Do you know any code for a 2D platform using kinematic ?

Kinematic means you manually update the position. To simulate gravity, you simply deduct from position.y a constant value every frame.

Delays are inevitable in multiplayer games. To combat this various features can be used like interpolation and prediction. The former is available in NetworkTransform, the latter would be up to you to implement (for the time being).

this is my game test with unity relay with 2 diffrent connection player can see himself Properly, but cant see other player Properly https://www.youtube.com/shorts/G2Qy-8gCe8s