Movement with custom network library

Hello,
I saw many examples with photon, but I’m using a Lidgren network library. So it doesn’t have serialization methods and so on. Everything is done by writing packets.

Basically, without much stuff making, sending client’s coordinates to server would be a huge spam and server probably would be flooded and would crash. In this case, I thought - let’s make a delay, for a short time, like 0.2 seconds and when let’s send our coordinates to the server. Also, if we would be just standing, unnecessary packets would be sent with the same position, so I did checking if position is atleast 0.1 or greater/less than last saved position. The whole code can be seen below, it’s attached to some player controllable controller.

using System.Collections;

using UnityEngine;

public class MultiplayerController : MonoBehaviour
{
    Vector3 lastPosition;

    void Start()
    {
        lastPosition = transform.position;
    }
   
    void Update()
    {
        if (Vector3.Distance(transform.position, lastPosition) >= 0.1)
        {
            lastPosition = transform.position;
            StartCoroutine(Delay());
        }
    }

    IEnumerator Delay()
    {
        yield return new WaitForSeconds(0.2f);
        GameNetwork.Instance().UpdatePosition(transform.position.x, transform.position.y, transform.position.z);
    }
}

This UpdatePosition is quite simple, just writing positions and sending it:

    public void UpdatePosition(float x, float y, float z)
    {
        NetOutgoingMessage om = s_client.CreateMessage();
        om.Write((byte)NetPacket.UpdatePlayer);
        om.Write((float)x);
        om.Write((float)y);
        om.Write((float)z);

        s_client.SendMessage(om, NetDeliveryMethod.ReliableOrdered);
    }

Okay, and when we receive other player position from the server:

case NetPacket.UpdatePlayer:
    int id = im.ReadInt32();
    float x = im.ReadFloat();
    float y = im.ReadFloat();
    float z = im.ReadFloat();
    GameObject tmp = GameObject.Find("Player " + id);
    if (tmp == null) return;
   
    tmp.transform.position = Vector3.Lerp(tmp.transform.position, new Vector3(x, y, z), Time.deltaTime * 10);
    break;

Server code just receives these 3 floats, and resends to anyone else except the source(who send) in the server with the id of player.

Well, it’s still kinda laggy movement. Probably cuz of too many sending packets or not, idk. Any ideas how to make it more smoothable?
Thanks.

What you need is interpolation or extrapolation, depends on what style of movement you want to synchronize.

Interpolation is good for uncalculatable changes in the velocity and direction of the objects moving. This is the most popular algorithm used of the two. This technique buffers incoming movement updates and lerps between them with in the given time, using the oldest of the buffered positions to not create stutters and noticable lag. Only bad thing about this algorithm is that the shown object position is always a bit behind the real position.

Extrapolation is the exact opposite, as it tries to forsee the next movement updates that will come. Most extrapolation algorithms use linear regression to calculate the next position that you will lerp to using the buffered movement updates, which is helpful for objects that have linear movement. The problem here is, that if the algorithm makes a wrong prediction the object will stutter to the correct position.