Help to refine the script of players of game objects

Hello. I’m working on a script for synchronizing objects in real time, everything is fine, interpolation works like it should, but jerks are observed, instead of smooth movement. Can someone look fresh and find a flaw in the code.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class SyncObj : NetworkBehaviour {

    public NetGM_Player netGM_Player = null;
    float maxRate = 0.06f; // частота отправки кадров

    Vector3 lastPosition = new Vector3 (0, 100, 0);

    Vector3 endPosition = new Vector3();
    Quaternion endRotation = new Quaternion();
    Vector3 startMarker_Position = new Vector3();
    Quaternion startMarker_Rotation = new Quaternion();
    float endTime = 0;
    float prec=0;

    float numscr = 0;

    float lastSendScren = 0;

    int factor = 1;

    public float delta =0;

    Rigidbody rig;

    Vector3 oldPosServ = new Vector3();
    Quaternion oldRotServ = new Quaternion();

    Vector3 newPosServ = new Vector3();
    Quaternion newRotServ = new Quaternion();

    // client
    List<ScreenTransform> _scrinsTransformPlayer = new List<ScreenTransform>();
    int numScreen = 0;

    // Use this for initialization
    void Start () {
        // query the current position of the object
        if (isClient) {
            CmdSyncStartPos (transform.position, transform.rotation);
            rig = GetComponent<Rigidbody> ();
            rig.isKinematic = true;
            rig.useGravity = false;
            rig.mass = 0f;
            rig.angularDrag = 0f;
            rig.interpolation = RigidbodyInterpolation.Interpolate;
        }
    }

    // Update is called once per frame
    void LateUpdate () {
        Client ();
    }

    void FixedUpdate()
    {
        ClientUpdate ();
        ServerFixedUpdate ();
    }

    //request the current object position from the server
    [Command]
    void CmdSyncStartPos(Vector3 pos, Quaternion rot)
    {
        if (transform.position != pos || transform.rotation != rot) {
            RpcSendAllNewTransform (transform.position, transform.rotation, Time.time);
        }
    }
    [ClientRpc]
    void RpcSendAllNewTransform(Vector3 newPosition, Quaternion newRotation, float time)
    {
        // add a new frame to the queue
        numScreen++;
        //Debug.Log ("Номер: " + numScreen + " Время: " + Time.fixedTime);
        _scrinsTransformPlayer.Add (new ScreenTransform(gameObject.GetInstanceID(), newPosition, newRotation, time, numScreen));
    }

    //// GM_local_main object to which the player has access, this object contains the time synchronized with the server
    //получаемое через метод GetServerTime();
    void Client()
    {
        if (!isClient)
            return;


    }

    void ClientUpdate()
    {
        if (!isClient)
            return;

        if (netGM_Player == null) {
            GameObject obj = GameObject.Find ("GM_local_main");
            if (obj != null) {
                netGM_Player = obj.GetComponent<NetGM_Player> ();
            }
        }


        if (netGM_Player != null) {

          
                 //interpolation
                 // If the screens are in the queue
            if (_scrinsTransformPlayer.Count > 0)
            {

                if (SerchScreen ()) {

                    startMarker_Position = transform.position;

                    //The end position is taken from the frame
                    endPosition = _scrinsTransformPlayer [0].position;

                    numscr = _scrinsTransformPlayer [0].number;

                    startMarker_Rotation = transform.rotation;
                    endRotation = _scrinsTransformPlayer [0].rotation;
                    //the time to which the object must reach its point
                    endTime = _scrinsTransformPlayer [0].time;
                    //remove a frame from the queue
                        _scrinsTransformPlayer.RemoveAt (0);

                }

            }
            //We calculate what percentage of the total path the object had to make to the current time
            float test = netGM_Player.GetServerTime () + Time.fixedTime;
            prec = ((netGM_Player.GetServerTime () + Time.fixedTime - maxRate*2) - (endTime)) / (maxRate);

            Debug.Log ("процент: " + prec + " Текущее время: " + (netGM_Player.GetServerTime() + Time.fixedTime - maxRate*2) + " endTime " + endTime + " номер " + numscr);

            //we interpolate the position of the object
            transform.position = Vector3.Lerp (startMarker_Position, endPosition, prec);
            transform.rotation = Quaternion.Slerp (startMarker_Rotation, endRotation, prec);
        }

    }

    void ServerFixedUpdate()
    {
        if (!isServer)
            return;

        if (lastSendScren == 0) {

            oldPosServ = transform.position;
            oldRotServ = transform.rotation;
            // 3 цикла: 3 * 0.2 = 0.6
            lastSendScren = 2;
            RpcSendAllNewTransform (transform.position, transform.rotation, Time.fixedTime);
        } else
            lastSendScren--;
    }

    // search for the right frame
    bool SerchScreen()
    {
        bool find = false;
        int k = 0;
        for (int i = 0; i < _scrinsTransformPlayer.Count; i++) {

            // (current server time) - (delay in 2 * maxRate)
            if (netGM_Player.GetServerTime () + Time.fixedTime - maxRate*2 >= _scrinsTransformPlayer [i].time
            ){
                    k = i;
                    find = true;
            }
        }
        if (find)
            for (int j = 0; j < k - 1; j++) {
                _scrinsTransformPlayer.RemoveAt (0);
            }
        return find;
    }
}

I apologize for google translate, but I really need help, I’m trying to find an error for a month now

transform.position = Vector3.Lerp (startMarker_Position, endPosition, prec);
to
transform.position = Vector3.SmoothDamp (transform.position, endPosition, ref velocity, maxRate); ?

I haven’t read through all your code, but something that stuck out to me is you are sending your updates to the clients on the default channel, which unless you’ve changed it is the reliable channel. If a ClientRpc to sync the position is sent and not received you don’t want it to try to resend it, as that information is already too old by the time it resends it. So I’d switch to using channel 1 for those.

I doubt that is your real problem though.

I solved my problem. Now I’m using UDP and Vector3.SmoothDamp instead of Vector3.lerp