Hello. I am working on a script for synchronizing objects in unet and can’t solve the problem of smooth movement of an object, this script receives the object's location from the server, everything is fine, interpolation works as it should, but jerks are observed instead of smooth movement. Maybe someone will take a fresh look 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 () { //запросить текущее положение объекта 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 (); } //запросить текущую позицию объекта у сервера [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) { // добавить новый кадр в очередь numScreen++; //Debug.Log ("Номер: " + numScreen + " Время: " + Time.fixedTime); _scrinsTransformPlayer.Add (new ScreenTransform(gameObject.GetInstanceID(), newPosition, newRotation, time, numScreen)); } //GM_local_main объект к которому игрок имеет доступ, в данном объекте содержется синхронизированное с сервером время, //получаемое через метод 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) { //интерполяция //Если скрины есть в очереди if (_scrinsTransformPlayer.Count > 0) { if (SerchScreen ()) { startMarker_Position = transform.position; //конечная позиция берется из кадра endPosition = _scrinsTransformPlayer [0].position; numscr = _scrinsTransformPlayer [0].number; startMarker_Rotation = transform.rotation; endRotation = _scrinsTransformPlayer [0].rotation; //время к которому объект должен достичь своей точки endTime = _scrinsTransformPlayer [0].time; //удалить кадр из учереди _scrinsTransformPlayer.RemoveAt (0); } } //рассчитываем какой процент от всего пути объект должен был сделать к текущему времени 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); //интерполируем положение объекта 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--; } // поиск подходящего кадра bool SerchScreen() { bool find = false; int k = 0; for (int i = 0; i < _scrinsTransformPlayer.Count; i++) { // текущее серверное время - задержка в 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; } 

}

It seems that the problem is not in this script, but in some particular mechanics of Unity. If you watch the beginning of this video https://www.youtube.com/watch?v=co_ACWIu4XU&t then you can see my problem in it, the object is synchronized, but it is jerking, although interpolation works well.

    2 answers 2

    Multiply by Time.deltaTime-jerks will not)

      I solved this problem by replacing Vector3.lerp with Vector3.SmoothDamp and using UDP, although I had to modify the processing of frames a bit. When using Smuzu, the control becomes less pleasant, it becomes tighter, but if you add advanced input to the script, you can make the smuz less and control will be normal.