Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Player Movement Lag

Discussion in 'Multiplayer' started by umutK16, May 23, 2024.

  1. umutK16

    umutK16

    Joined:
    Nov 3, 2022
    Posts:
    4
    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
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4. using TMPro;
    5. using Random = UnityEngine.Random;
    6. using Unity.Netcode;
    7. using UnityEngine.SceneManagement;
    8.  
    9. public class Movement : NetworkBehaviour
    10. {
    11.     private Rigidbody2D rb;
    12.     private Animator anim;
    13.     [SerializeField] private float Speed;
    14.     [SerializeField] private float JumpForce;
    15.     [SerializeField] private bool Ice;
    16.     private float move;
    17.  
    18.     private enum MovementState { idle, runing, falling, jumping, Death}
    19.  
    20.     [SerializeField] private LayerMask JumpableGround;
    21.  
    22.     public bool CanMove = false;
    23.     public bool CanTakeDamage = false;
    24.  
    25.     private NetworkVariable<Vector2> NewVelocity = new NetworkVariable<Vector2>();
    26.  
    27.     private void Start()
    28.     {
    29.         anim = GetComponent<Animator>();
    30.         rb = GetComponent<Rigidbody2D>();
    31.         NewVelocity.Value = rb.velocity;
    32.         CanMove = true;
    33.         CanTakeDamage = true;
    34.     }
    35.     private void Update()
    36.     {
    37.         if (IsOwner)
    38.         {  
    39.             if (CanMove)
    40.             {
    41.                 move = Input.GetAxisRaw("Horizontal");
    42.  
    43.                 if (Ice)
    44.                     rb.AddForce(new Vector2(move * Speed, rb.velocity.y));
    45.                 else
    46.                     rb.velocity = new Vector2(move * Speed, rb.velocity.y);
    47.  
    48.                 if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.W))
    49.                 {
    50.                     if (IsGrounded())
    51.                     {
    52.                         if (Ice)
    53.                             rb.velocity = new Vector2(rb.velocity.x, JumpForce / 2);
    54.                         else
    55.                             rb.velocity = new Vector2(rb.velocity.x, JumpForce);
    56.                     }
    57.                 }
    58.                 UpdatePositionServerRpc(rb.velocity);
    59.             }
    60.         }
    61.         else
    62.         {
    63.             rb.velocity = NewVelocity.Value;
    64.         }
    65.         UpdateAnim();
    66.     }
    67.  
    68.    [ServerRpc]
    69.     private void UpdatePositionServerRpc(Vector2 newValue)
    70.     {
    71.         NewVelocity.Value = newValue;
    72.     }
    73.  
    74.  private void OnCollisionEnter2D(Collision2D collision)
    75.     {
    76.         if (collision.gameObject.CompareTag("ice"))
    77.         {
    78.             Ice = true;
    79.         }
    80.     }
    81.     private void OnCollisionExit2D(Collision2D collision)
    82.     {
    83.         if (collision.gameObject.CompareTag("ice"))
    84.         {
    85.             Ice = false;
    86.         }
    87.     }
    88.     private bool IsGrounded()
    89.     {  
    90.         return Physics2D.BoxCast(coll.bounds.center, coll.bounds.size, 0f, Vector2.down, 0.05f, JumpableGround);
    91.     }
    92.     private void UpdateAnim()
    93.     {
    94.         if(CanMove)
    95.         {
    96.             MovementState state;
    97.             if (rb.velocity.x > 0.1f)
    98.             {
    99.                 state = MovementState.runing;
    100.                 sprite.flipX = false;
    101.             }
    102.             else if (rb.velocity.x < -0.1f)
    103.             {
    104.                 state = MovementState.runing;
    105.                 sprite.flipX = true;
    106.             }
    107.             else
    108.             {
    109.                 state = MovementState.idle;
    110.             }
    111.  
    112.             if (rb.velocity.y > 0.1f)
    113.             {
    114.                 state = MovementState.jumping;
    115.             }
    116.             else if (rb.velocity.y < -0.1f)
    117.             {
    118.                 state = MovementState.falling;
    119.             }
    120.             anim.SetInteger("State", (int)state);
    121.         }
    122.     }
    123. }
    124.  
    125.  
     
    Last edited: May 23, 2024
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    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).
     
  3. umutK16

    umutK16

    Joined:
    Nov 3, 2022
    Posts:
    4
    Thank you for helping me. Do you mean that I should do the character movement without using Rigidbody?
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    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.
     
  5. umutK16

    umutK16

    Joined:
    Nov 3, 2022
    Posts:
    4
    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 ?
     
  6. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,922
    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).
     
  7. umutK16

    umutK16

    Joined:
    Nov 3, 2022
    Posts:
    4