Search Unity

Network Transform lags

Discussion in 'Multiplayer' started by Royall, Jun 19, 2015.

  1. Royall

    Royall

    Joined:
    Jun 15, 2013
    Posts:
    121
    Does anyone know how to fix the glitchy/laggie movement of the network transform.
    I already tried to update to Unity 5.1.1 where they said transform interpolation has been fixed.

    I use standard Network Transform settings, tested localhost with a server and 1 client.

    Movement looks far from smooth :(
     
    joaoVictorCardoso likes this.
  2. Qiu-Jian

    Qiu-Jian

    Joined:
    May 22, 2013
    Posts:
    3
    @Royall,try "Transform sync more". I found it more smooth when using CharaterController mode instead of Transform mode.
     
  3. Royall

    Royall

    Joined:
    Jun 15, 2013
    Posts:
    121
    I only see
    Sync none
    Sync Transform
    Sync Rigidbody 2D
    Synv Rigidbody 3D
    Sync Character Controller

    Unfortunately Sync Transform and Sync character controller both look laggy...

    What do you mean with sync more?
     
  4. SuperNeon

    SuperNeon

    Joined:
    Mar 16, 2014
    Posts:
    85
    Transform Mode is not smooth at all.
    It just apply the new position received, so your game object will be teleported.

    Rigidbody/Character controller should do the job in certain manners, the last velocity is applied each frame but you can still have the feeling of teleportation.

    I did my own NetworkTransform implementation inspired by Quake 3 and unreal.
    http://fabiensanglard.net/quake3/network.php


    The idea is:
    • for the local character:
    - process the gameplay
    - send the current state of the character to the server.
    - The server valid the state and send it to the other clients.

    • for the other characters:
    - received new character state and put it in an array.
    - find the closest saved states (received by the server) for the current time stamp (Time.time - interpolationTime)
    - interpolate between the closest states and the previous one and apply the result


    If you want a solid net code I don't think NetworkTransform is enought. If it is for prototyping purpose it can be good but don't expect too much ^_^

    I hope it can help.
     
    codestage likes this.
  5. Royall

    Royall

    Joined:
    Jun 15, 2013
    Posts:
    121
    I highly doubt the Network Transform is just some position and rotation sending. There are parameters for interpolation but they don't do much... I get the same results with transform mode as rigidbody and charcontroller mode.

    They sell the HLAPI as a simple and flexible solution for multiplayer games where you can convert your single player game with 3 mouse clicks. I can understand if they don't offer state of the art movement interpolation but they can atleast release something decent because right know it looks the Network Transform is just not usable in any way...

    It maybe is even better to just syncvar some positions and just lerp between them atm...
     
    joaoVictorCardoso likes this.
  6. SuperNeon

    SuperNeon

    Joined:
    Mar 16, 2014
    Posts:
    85
    If you take a look inside the assembly code you will see I'm right.
    Interpolation parameters is used for the others types of Sync.

    Cheers
     
  7. Royall

    Royall

    Joined:
    Jun 15, 2013
    Posts:
    121
    Any chance you could share your interpolation code?
     
  8. SuperNeon

    SuperNeon

    Joined:
    Mar 16, 2014
    Posts:
    85
  9. MFKJ

    MFKJ

    Joined:
    May 13, 2015
    Posts:
    264
    hey guys its 2016 Oct, any progress to control lag on network i follow unity offical tut
    INTRODUCTION TO A SIMPLE MULTIPLAYER EXAMPLE
    but the problem its performance is low. There is lag between my VR player instance and normal player instance. how do contorl?
     
  10. JesusChrist17

    JesusChrist17

    Joined:
    Sep 17, 2016
    Posts:
    12

    Hey bro did you solve it? i did this example, but i see a little lag the movement player
     
  11. MFKJ

    MFKJ

    Joined:
    May 13, 2015
    Posts:
    264
    I didn't find any solution yet but there are different option in network transform that can be used to control lag (i guess).
     
  12. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    I use the following code for position:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. public class Object_SyncPosition : NetworkBehaviour {
    6.  
    7.     private Transform myTransform;
    8.     [SerializeField] float lerpRate = 5;
    9.     [SyncVar] private Vector3 syncPos;
    10. //    private NetworkIdentity theNetID;
    11.  
    12.     private Vector3 lastPos;
    13.     private float threshold = 0.5f;
    14.  
    15.  
    16.     void Start () {
    17.         myTransform = GetComponent<Transform> ();
    18.         syncPos = GetComponent<Transform>().position;
    19.     }
    20.  
    21.  
    22.     void FixedUpdate () {
    23.         TransmitPosition ();
    24.         LerpPosition ();
    25.     }
    26.  
    27.     void LerpPosition () {
    28.         if (!hasAuthority) {
    29.             myTransform.position = Vector3.Lerp (myTransform.position, syncPos, Time.deltaTime * lerpRate);
    30.         }
    31.     }
    32.  
    33.     [Command]
    34.     void Cmd_ProvidePositionToServer (Vector3 pos) {
    35.         syncPos = pos;
    36.     }
    37.  
    38.     [ClientCallback]
    39.     void TransmitPosition () {
    40.         if (hasAuthority  && Vector3.Distance(myTransform.position, lastPos) > threshold) {
    41.             Cmd_ProvidePositionToServer (myTransform.position);
    42.             lastPos = myTransform.position;
    43.         }
    44.     }
    45. }
     
  13. MFKJ

    MFKJ

    Joined:
    May 13, 2015
    Posts:
    264
    So it is the replacement of Network transform? or i use this script with network transform also
     
  14. Xuzon

    Xuzon

    Joined:
    Mar 21, 2014
    Posts:
    83
    I did this solution because UNET's network transform... doesn't interpolate nor predicts, I don't know why is there an interpolation factor :/

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. public class NetworkMovement : NetworkBehaviour {
    6.     #region Properties
    7.     [SerializeField]
    8.     protected Transform target;
    9.  
    10.     #region Setup
    11.     [Header("Setup")]
    12.     [Range(0,10)] public int SendRate = 2;
    13.     [Range(0,2)] public float movementThreshold = 0.2f;
    14.     [Range(0,30)] public float angleThreshold = 5;
    15.     [Range(0, 10)] public float distanceBeforeSnap = 4;
    16.     [Range(0,90)] public float angleBeforeSnap = 40;
    17.     #endregion
    18.  
    19.     #region Interpolation
    20.     [Header("Interpolation")]
    21.     [Range(0,1)] public float movementInterpolation = 0.1f;
    22.     [Range(0,1)] public float rotationInterpolation = 0.1f;
    23.     #endregion
    24.  
    25.     #region Prediction
    26.     public float thresholdMovementPrediction = 0.7f;
    27.     public float thresholdRotationPrediction = 15;
    28.     #endregion
    29.  
    30.     #region ProtectedProperties
    31.     protected Vector3 lastDirectionPerFrame = Vector3.zero;
    32.     protected Vector3 lastPositionSent = Vector3.zero;
    33.     protected Quaternion lastRotationSent = Quaternion.identity;
    34.     protected Quaternion lastRotationDirectionPerFrame = Quaternion.identity;
    35.     protected bool send = false;
    36.     protected bool sending = false;
    37.     protected int count = 0;
    38.     #endregion
    39.  
    40.     #endregion
    41.  
    42.     #region Logic
    43.     void FixedUpdate () {
    44.         if (isLocalPlayer) {
    45.             sendInfo();
    46.         } else {
    47.             recontiliation();
    48.         }
    49.     }
    50.  
    51.     protected void sendInfo() {
    52.         if (send) {
    53.             if (count == SendRate) {
    54.                 count = 0;
    55.                 send = false;
    56.                 Vector3 v = target.position;
    57.                 Quaternion q = target.rotation;
    58.                 CmdSendPosition(v,q);
    59.             } else {
    60.                 count++;
    61.             }
    62.         } else {
    63.             checkIfSend();
    64.         }
    65.     }
    66.     protected void checkIfSend() {
    67.         if (sending) {
    68.             send = true;
    69.             sending = false;
    70.             return;
    71.         }
    72.         Vector3 v = target.position;
    73.         Quaternion q = target.rotation;
    74.         float distance = Vector3.Distance(lastPositionSent, v);
    75.         float angle = Quaternion.Angle(lastRotationSent, q); ;
    76.         if (distance > movementThreshold || angle > angleThreshold) {
    77.             send = true;
    78.             sending = true;
    79.         }
    80.     }
    81.     protected void recontiliation() {
    82.         Vector3 v = target.position;
    83.         Quaternion q = target.rotation;
    84.         float distance = Vector3.Distance(lastPositionSent, v);
    85.         float angle = Vector3.Angle(lastRotationSent.eulerAngles, q.eulerAngles);
    86.         if (distance > distanceBeforeSnap) {
    87.             target.position = lastPositionSent;
    88.         }
    89.         if (angle > angleBeforeSnap) {
    90.             target.rotation = lastRotationSent;
    91.         }
    92.         //prediction
    93.         v += lastDirectionPerFrame;
    94.         q *= lastRotationDirectionPerFrame;
    95.         //interpolation
    96.         Vector3 vLerp = Vector3.Lerp(v, lastPositionSent, movementInterpolation);
    97.         Quaternion qLerp = Quaternion.Lerp(q, lastRotationSent, rotationInterpolation);
    98.             target.position = vLerp;
    99.             target.rotation = qLerp;
    100.     }
    101.     #endregion
    102.  
    103.     #region OverNetwork
    104.     [Command (channel = 1)]
    105.     protected void CmdSendPosition(Vector3 newPos,Quaternion newRot) {
    106.         RpcReceivePosition(newPos, newRot);
    107.     }
    108.  
    109.     [ClientRpc(channel = 1)]
    110.     protected void RpcReceivePosition(Vector3 newPos,Quaternion newRot) {
    111.         int frames = (SendRate + 1);
    112.         lastDirectionPerFrame = newPos - lastPositionSent;
    113.         //right now prediction is made with the new direction and amount of frames
    114.         lastDirectionPerFrame /= frames;
    115.         if (lastDirectionPerFrame.magnitude > thresholdMovementPrediction) {
    116.             lastDirectionPerFrame = Vector3.zero;
    117.         }
    118.         Vector3 lastEuler = lastRotationSent.eulerAngles;
    119.         Vector3 newEuler = newRot.eulerAngles;
    120.         if (Quaternion.Angle(lastRotationDirectionPerFrame, newRot) < thresholdRotationPrediction) {
    121.             lastRotationDirectionPerFrame = Quaternion.Euler(( newEuler - lastEuler ) / frames);
    122.         }else {
    123.             lastRotationDirectionPerFrame = Quaternion.identity;
    124.         }
    125.         lastPositionSent = newPos;
    126.         lastRotationSent = newRot;
    127.     }
    128.     #endregion
    129. }
    130.  
     
    toni770 likes this.
  15. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Replace
     
    joaoVictorCardoso likes this.
  16. xuchenCN

    xuchenCN

    Joined:
    Jul 4, 2016
    Posts:
    1
    Thanks upstairs , look lot of topic finally fixed that issue , I made a sync transform (position and rotation)

    Code (CSharp):
    1.  
    2.    class Play_syncRotation : NetworkBehaviour
    3.    {
    4.       [SyncVar]
    5.       private Quaternion playerQuaternion;
    6.  
    7.       [SyncVar]
    8.       private Vector3 newPosition;
    9.  
    10.       private float speed;
    11.       private float syncThreshold;
    12.       private float rotationSpeed;
    13.  
    14.  
    15.       void Start()
    16.       {
    17.          speed = GetComponent<TPlayerController>().moveSpeed;
    18.          syncThreshold = GetComponent<TPlayerController>().syncPositionThreshold;
    19.          rotationSpeed = GetComponent<TPlayerController>().rotationSpeed;
    20.       }
    21.  
    22.       void FixedUpdate()
    23.       {
    24.          if (!isLocalPlayer)
    25.          {
    26.             if(transform.localRotation != playerQuaternion)
    27.             {
    28.                transform.localRotation = Quaternion.Lerp(transform.localRotation, playerQuaternion, Time.deltaTime * rotationSpeed);
    29.             }
    30.             Move_Torwards(transform.transform.position, newPosition, speed);
    31.  
    32.          }
    33.        
    34.       }
    35.    
    36.  
    37.       [Command]
    38.       void CmdProviderNewPositionToServer(Vector3 playerPos, Quaternion playerQuaternion)
    39.       {
    40.          this.newPosition = playerPos;
    41.          this.playerQuaternion = playerQuaternion;
    42.       }
    43.  
    44.       [Client]
    45.       public void Transmit(Vector3 playerPos, Quaternion playerQuaternion)
    46.       {
    47.          if (isLocalPlayer)
    48.          {
    49.             CmdProviderNewPositionToServer(playerPos, playerQuaternion);
    50.          }
    51.       }
    52.  
    53.  
    54.       private bool Move_Torwards(Vector3 startPos, Vector3 endPos, float moveMax)
    55.       {
    56.          if (Vector3.Distance(startPos, endPos) <= syncThreshold)
    57.          {
    58.             return true;
    59.          }
    60.          else
    61.          {
    62.             Vector3 moveForward = endPos - startPos;
    63.             moveForward.y = 0;
    64.             moveForward.Normalize();
    65.             float maxDistanceDelta = Time.deltaTime * moveMax;
    66.             Vector3 targetPos = Vector3.MoveTowards(transform.position, endPos, maxDistanceDelta);
    67.             transform.position = targetPos;
    68.             return false;
    69.          }
    70.  
    71.       }
    72.    }
    AND the character controller

    Code (CSharp):
    1.  
    2.    class TPlayerController : NetworkBehaviour
    3.    {
    4.  
    5.       [SerializeField]
    6.       private float m_moveSpeed = 5;
    7.       public float moveSpeed { get { return m_moveSpeed; } }
    8.  
    9.       [SerializeField]
    10.       private float m_syncPositionThreshold = 0.25f;
    11.       public float syncPositionThreshold { get { return m_syncPositionThreshold; } }
    12.  
    13.       [SerializeField]
    14.       private int m_rotationSpeed = 15;
    15.       public int rotationSpeed { get { return m_rotationSpeed; } }
    16.  
    17.       void Awake()
    18.       {
    19.  
    20.       }
    21.  
    22.       void Start()
    23.       {
    24.          if (isLocalPlayer)
    25.          {
    26.             GetComponent<Play_syncRotation>().Transmit(transform.transform.position, transform.rotation);
    27.          }
    28.  
    29.       }
    30.  
    31.       void Update()
    32.       {
    33.          if (!isLocalPlayer)
    34.          {
    35.             return;
    36.          }
    37.          // CrossPlatformInputManager.GetButtonDown("w");
    38.  
    39.          float h = CrossPlatformInputManager.GetAxis("Horizontal");
    40.          float v = CrossPlatformInputManager.GetAxis("Vertical");
    41.  
    42.          if (h != 0 || v != 0)
    43.          {
    44.             GetComponent<Animator>().SetBool("Run", true);
    45.          }
    46.          else if (h == 0 && v == 0)
    47.          {
    48.             GetComponent<Animator>().SetBool("Run", false);
    49.          }
    50.  
    51.          // transFormValue = (v * Vector3.forward + h * Vector3.right) * Time.deltaTime;
    52.          Vector3 m_CamForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
    53.          Vector3 transFormValue = v * m_CamForward + h * Camera.main.transform.right;
    54.          float distance = 0;
    55.          if (transFormValue.x != 0 || transFormValue.z != 0)
    56.          {
    57.             distance = Vector3.Distance(transform.position, transFormValue);
    58.             //this.rotation = Quaternion.LookRotation(transFormValue).eulerAngles;
    59.             //CmdChangeRot(this.rotation);
    60.             //transform.rotation = Quaternion.Euler(rotation);
    61.             //transform.localRotation = Quaternion.LookRotation(transFormValue);
    62.             Quaternion lerpRota = Quaternion.Lerp(transform.localRotation, Quaternion.LookRotation(transFormValue), Time.deltaTime * 15);
    63.             if (transform.localRotation != lerpRota)
    64.             {
    65.                transform.localRotation = lerpRota;
    66.                //Debug.Log("sent " + transform.localRotation);
    67.                //GetComponent<Play_syncRotation>().TransmitRotation(transform.localRotation);
    68.             }
    69.  
    70.             //Debug.Log("update : " + GetComponent<NetworkIdentity>().netId + ":" + transform.rotation);
    71.             //Debug.Log(h + "-" + v + transFormValue + "--" + m_TurnAmount);
    72.  
    73.             // transform.Rotate(0, 90, 0);
    74.             transFormValue *= Time.deltaTime;
    75.  
    76.             // Debug.Log("transFormValue" + );
    77.  
    78.             transform.Translate(transFormValue * m_moveSpeed, Space.World);
    79.             if (distance >= m_syncPositionThreshold)
    80.             {
    81.                GetComponent<Play_syncRotation>().Transmit(transform.transform.position, transform.localRotation);
    82.             }
    83.  
    84.          }
    85.          Camera.main.transform.LookAt(this.transform);
    86.          Camera.main.transform.position = new Vector3(this.transform.position.x, this.transform.position.y + 8f, this.transform.position.z + 8f);
    87.       }
    88.  
    89.    }
    And you can add a Queue in the Play_syncRotation to make move smoothly like this

    Code (CSharp):
    1.  if (moveQueue.Count > 0)
    2.          {
    3.  
    4.             target.GetComponent<Animator>().SetBool("Run", true);
    5.             MoveAction action = moveQueue.Peek();
    6.             if (Move_Torwards(target, target.transform.position, action.to, action.speed)) {
    7.                moveQueue.Dequeue();
    8.             }
    9.             Debug.Log("play move : " + target.transform.position + ":" + action.to + " rest action " + moveQueue.Count);
    10.             //StartCoroutine();
    11.          }
     
  17. zazoum

    zazoum

    Joined:
    Sep 3, 2011
    Posts:
    78
    I'm currently learning Unity's Networking through Merry Fragmas video tutorial and the documentation. I don't know if I fall in the same category as the people in this topic but I make a 2D top down arena shm'up and I'm facing the following issue:
    I see my player move smoothly and the others not, and my friends can see their players run smoothly and the others not.
    I tried all sorts of player movement technics in the Player script, I tried all kind of settings in Transform and Transform Child Network (even removing them) and the problem stays the same. They don't sync.

    Am I having the same problem as the posters in this thread?

    PS: My Player doesn't have a character controller and it doesn't move by forces.
     
  18. allcoder

    allcoder

    Joined:
    Jun 4, 2015
    Posts:
    13

    i did an update to get rotation too:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3.  
    4. public class TransformMotion : NetworkBehaviour
    5. {
    6.  
    7.     [SyncVar]
    8.     private Vector3 syncPos;
    9.  
    10.     [SyncVar]
    11.     private float syncYRot;
    12.  
    13.     private Vector3 lastPos;
    14.     private Quaternion lastRot;
    15.     private Transform myTransform;
    16.     [SerializeField]
    17.     private float lerpRate = 10;
    18.     [SerializeField]
    19.     private float posThreshold = 0.5f;
    20.     [SerializeField]
    21.     private float rotThreshold = 5;
    22.  
    23.     // Use this for initialization
    24.     void Start()
    25.     {
    26.         myTransform = transform;
    27.     }
    28.  
    29.     // Update is called once per frame
    30.     void FixedUpdate()
    31.     {
    32.         TransmitMotion();
    33.         LerpMotion();
    34.     }
    35.  
    36.     [Command]
    37.     void Cmd_ProvidePositionToServer(Vector3 pos, float rot)
    38.     {
    39.         syncPos = pos;
    40.         syncYRot = rot;
    41.     }
    42.  
    43.     [ClientCallback]
    44.     void TransmitMotion()
    45.     {
    46.         if(hasAuthority)
    47.         {
    48.             if (Vector3.Distance(myTransform.position, lastPos) > posThreshold || Quaternion.Angle(myTransform.rotation, lastRot) > rotThreshold)
    49.             {
    50.                 Cmd_ProvidePositionToServer(myTransform.position, myTransform.localEulerAngles.y);
    51.  
    52.                 lastPos = myTransform.position;
    53.                 lastRot = myTransform.rotation;
    54.             }
    55.         }
    56.     }
    57.  
    58.     void LerpMotion()
    59.     {
    60.         if (!hasAuthority)
    61.         {
    62.             myTransform.position = Vector3.Lerp(myTransform.transform.position, syncPos, Time.deltaTime * lerpRate);
    63.  
    64.             Vector3 newRot = new Vector3(0, syncYRot, 0);
    65.             myTransform.rotation = Quaternion.Lerp(myTransform.rotation, Quaternion.Euler(newRot), Time.deltaTime * lerpRate);
    66.         }
    67.     }
    68. }
    69.  
    [/code]
     
    Khyrid and pKallv like this.
  19. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,191
    Great, i have a separate script for that.
     
  20. Pappi11

    Pappi11

    Joined:
    Mar 27, 2014
    Posts:
    9
    I say Fork lerping and just made the update tick 128 times a sec and im sending the server "raw" vectors I've had 0 problems and the movement is smooth enough for a fast paste fps. Everything in real time. Perfect.
     
  21. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    You are not interpolating? And you are sending raw vectors 128 times per second? PER CLIENT? THAT THE SERVER THEN HAS TO RESEND TO ALL OTHER CLIENTS?

    Why are you not interpolating? Sending data 20 times per second is plenty. 20 times per second is what a lot of realtime games use. Such as Counterstrike.


    And btw, it's not going to even work to send updates 128 times a second. Atleast not over the wire. On local network it will probably be fine. But super wasteful
     
    Last edited: Nov 8, 2017
  22. Pappi11

    Pappi11

    Joined:
    Mar 27, 2014
    Posts:
    9
    Yeah ik but its a lan game, Im not using interpolation because it just doesnt work like i want it to. Its way more enjoyable to play when you know that when you are behind a wall you really are behind that wall and not in the middle of nowhere like with interpolation. We have been having lots more fun without interpolation and had 0 problems with my server giving up on itself. When we play online i just drop the tick to around 60-90, all fine. =))
     
  23. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Well, let me give my oppinion on your reasoning. If you are using 100% client sided shooting.

    Then if you are in the open. Then walk behind a wall. But before the client gets that message. It shoots. Then your problem is not solved. And you are wasting processing power.

    If you are using server sided shooting (Server authority). Assuming you are properly doing lag compensation. Your argument still makes little sense. If you send 20 times a second. You could get away with 50 miliseconds of lag for the client that goes behind a wall.

    So if you are not using a Server authoritative shooting model or you are not compensating for lag. Your argument makes no sense.

    Just something to consider.
     
  24. Pappi11

    Pappi11

    Joined:
    Mar 27, 2014
    Posts:
    9
    You seriously dont play fps dont you? Please come back when you have atleast 4000+ hours in a COMPETITIVE fps game and then give me a valid reason to use interpolation. 50ms way too much when you can get max 1-3 ms of lag with interpolation ill use it. =)
     
  25. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    "When you can get max 1-3ms of lag with interpolation i'll use it". You obviously don't understand. That can only happen if you have a sendrate that is very high, at which point. Interpolation is no longer needed.

    As for the competitive FPS game thing. It's quite unrelated imo. But if that's your way of ranking credibility. I'll give you some info to at least try to satisfy it.

    * I have played 6600 hours of ArmA 3 (Probably doesn't fit your definition of a competitive FPS, but they use interpolation and extrapolation)
    * I have about 1000 hours of Counterstrike Global Offensive (They use 100ms of latency. They send movements 20 times a second and use two updates as buffer for the interpolation).
    * 400+ hours of Counterstrike Source
     
  26. Driiades

    Driiades

    Joined:
    Oct 27, 2015
    Posts:
    151
    "two updates as buffer for the interpolation"

    They send 2 positions each time they want to sync ? (so each 1/20 -> 0.05 s ?)
     
  27. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Let me demonstrate of how a client would deal with incoming position updates from the server about other clients. This is Counterstrike specific but quite useful.

    Client get's a position. It stores it. It then gets another one. And it then starts interpolating from the current position to the first recieved position at a speed that makes it complete by the time the next one arrives. And they just continue this pattern. That way, if a position is not recieved. It has a backup one to interpolate to.

    My source is this: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
    Which I used when I researched Lag compensation, if you are intrested. My results are here: https://twotenpvp.github.io/lag-compensation-in-unity.html
     
  28. Driiades

    Driiades

    Joined:
    Oct 27, 2015
    Posts:
    151
    yes i'm based also on this article.
    For the moment i do not the error interpolation that's why i get jittering.

    But this article say to store all positions from server and play 100ms in the past. Not just the last and the current position.
     
  29. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Well. Just make sure you don't do what most amature network programmers do when they try interpolation. They usually lerp between current pos and target with a fixed amount * time.deltatime as (t)
     
  30. Driiades

    Driiades

    Joined:
    Oct 27, 2015
    Posts:
    151
    Haha like the HLAPI ?
    no :p

    How do you sync the current timestamp for movement state ?

    For the moment I sync serverTimestamp when client connect and send that each time i sync movement. But i dunno if something is better ^^ .
     
  31. ScoobyNooby

    ScoobyNooby

    Joined:
    Nov 14, 2017
    Posts:
    45
    Fuestrine likes this.
  32. eco_bach

    eco_bach

    Joined:
    Jul 8, 2013
    Posts:
    1,601
    pKallv and allcoder

    Thanks!!! This is a very helpful thread.

    However I am experiencing an issue where both examples ONLY work one way

    ie when the motion is done on the Host (server) Client, the Remote Client is updated properly

    The reverse does not work! ie position updates on the Remote Client are NOT updated on the Host client.

    I have tested several times. Something to do with Local Player Authority on my Network Identity component or??

    Any chance you can suggest a solution?
     
    Last edited: Dec 5, 2017
  33. joaoVictorCardoso

    joaoVictorCardoso

    Joined:
    Nov 19, 2017
    Posts:
    3

    Thanks dudes (I have no idea why such a great need to discuss something so simple) BUT
    You have helped me a lot on this topic. Let me tell the laity about this:

    1º = to have smooth movements and without use of additional codes do so:
    * set NETWORK SEND RATE (SECONDS): 20;

    * MOVEMENT THRESHOLD: 0.001 (default)
    * VELOCITY THRESHOLD: 0.03 (or lower)
    * SNAP THRESHOLD: 0.01 (or lower)
    * INTERPOLATE MOVEMENT FACTOR: 1 (it's fine)

    do this in the Movement settings within the Network Transform script.
    And ok! now you have a super smooth movement and equal to what is needed for a professional game!
    Thanks for the help, this topic was clear to me! I use a notebook without a video card: i5 (3rd generation), 8GB RAM, Windows 7 SP1
     
    wlwl2 likes this.
  34. ricksto87

    ricksto87

    Joined:
    May 6, 2015
    Posts:
    2

    This is perfect! works flawlessly and so simple
     
  35. diegodimap

    diegodimap

    Joined:
    Jun 4, 2017
    Posts:
    6
    I am making a FPS multiplayer (cliche).
    Everything is working fine, but when I shoot from the player (the server works fine),
    my bullet in the player screen has a LAG on the rotation.
    On the other players it seems to be working fine!
    What can be it? I know I am supposed to render a local bullet for my player and a server bullet for other players but when I do this I have two bullets coming out of the gun on the localplayer :(
    I tried to solve this with layers, like: DO NOT render server bullets, only my local one. But when I do this I can't see the other players bullets!
    Can I render only the server bullets that were not created by me? I mean, how can I know the network objects created by my player ?

    Code (CSharp):
    1. if (isLocalPlayer) {
    2.             if (Input.GetMouseButtonDown(0) && ak.getAmmoRifleLoaded() > 0) {
    3.                 if (!isServer) {
    4.                  
    5.                     CmdPlaceBala();
    6.                 }
    7.                 if (isServer) {
    8.                     balaInstance = Instantiate(balaServer, bocaCano.transform.position, bocaCano.transform.rotation);
    9.                  
    10.  
    11.                     balaInstance.GetComponent<Rigidbody>().AddForce(bocaCano.transform.forward * velocidadeBala);
    12.                     Destroy(balaInstance, 5.0f);
    13.  
    14.                     NetworkServer.Spawn(balaInstance);
    15.                 }
    16.             }
    17.  
    18.         }
    19.     }
    20.  
    21.     [Command]
    22.     void CmdPlaceBala() { //precisa começar com CMD
    23.  
    24.        
    25.         balaInstance = Instantiate(balaServer, bocaCano.transform.position, bocaCano.transform.rotation);
    26.  
    27.         balaInstance.GetComponent<Rigidbody>().AddForce(bocaCano.transform.forward * velocidadeBala);
    28.         Destroy(balaInstance, 5.0f);
    29.  
    30.      
    31.  
    32.         NetworkServer.Spawn(balaInstance);
    33.  
    34.     }
    Thank you!
     

    Attached Files:

  36. Denzy77

    Denzy77

    Joined:
    Jan 5, 2019
    Posts:
    4
    Dude. You are a freaking legend. Works really good tbh with a bit of unnoticable lag.
    Check it out:
    (unlisted)