Interpolation /Extrapolation question

So i am trying to get smooth moment over network (cloud service) for my game, updating with OnSerializeNetwork(), every 100 ms.

As far as i understand it then i want to look for having a buffered state time that is bigger then the current network time minus some time above 100 ms. In this manner i know that i received a new message which i can use for interpolation between two buffered states (as new as possible).
If not then i lost some packages i want to fight jitter by extrapolating my movement based on the latest buffered states position added with my latest velocity * with the time between my network time - some interval (what i used earlier) - my last buffered states time-stamp.

Now i am using a rigidbody on all chars, but it is set to kinematic for all players that is NOT mine.
I do receive my msgs most of the time and my ping is around 35.

[code2=csharp]void Update()
{
if (_nStates.Count < 2) return;

//interpolate
double interpolationTime = PhotonNetwork.time - netInterval; //(0.15, we update every 100ms)
if (_nStates[0].time > interpolationTime)
{
for (int i = 0; i < _nStates.Count; i++)
{
if (_nStates.time <= interpolationTime || i == _nStates.Count - 1)
{
NetworkPackageState newestPackage = _nStates[i - 1];
NetworkPackageState oldestPackage = _nStates;

double setTimer = newestPackage.time - oldestPackage.time;
double t = (setTimer > 0.0001) ? interpolationTime - oldestPackage.time / setTimer : 0.0F;

transform.position = Vector3.Lerp(oldestPackage.position, newestPackage.position, (float)t);
transform.rotation= Quaternion.Slerp(oldestPackage.rotation, newestPackage.rotation, (float)t);
}
}
}
else //Extrapolate
{
NetworkPackageState latest = _nStates[0];
float extrapolationTimer = (float)(interpolationTime - latest.time);

//dont extrapolate too "far"
if (extrapolationTimer < 0.5F)
{
transform.position = latest.position + latest.velocity * extrapolationTimer;
}
}
}
}

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.isWriting)
{
stream.SendNext(transform.position);
stream.SendNext(transform.rotation);
stream.SendNext(rigidbody.velocity);
stream.SendNext(PhotonNetwork.time);
}
else
{
//Recieved position, rotation and time stamp it is send
Vector3 position = (Vector3)stream.ReceiveNext();
Quaternion rotation = (Quaternion)stream.ReceiveNext();
Vector3 velocity = (Vector3)stream.ReceiveNext();
double t = (double)stream.ReceiveNext();

//Create new networkpackage and save it - remove packages if it gets too big
NetworkPackageState package = new NetworkPackageState(position, rotation, velocity, t);
_nStates.Insert(0, package);
if (_nStates.Count > 10) _nStates.RemoveAt(10);
}
}[/code2]

I only try to look at position at the moment as rotation is extremly limited (can be two different values around the Y-axis).

If anyone can guide me in some direction or tell me if i made a big mistake, then i would be very happy :mrgreen:

Comments

  • Seemed to work better if i simply didn't use kinematic rigidbody's - and updated velocity on each update combined with a distance check to see if i was too much out of sync.