Jump to content
  • Advertisement
Crayz92

Inconsistent interpolation velocity, and interp + lag compensation?

Recommended Posts

My interpolation is having some jitters, and I think I've boiled it down to an inconsistent velocity based on the distance of point A to B.  Is there a standard way of ensuring my interpolations are consistent?  I'm not performing any sort of extrapolation, but I feel that might be the key, I'm just struggling a bit with the actual implementation of it.  Here's my code, called every frame for every entity:

 

var nextFrameIdx = GetFrameInPast(interp.Frames, 0.1f);

// no available frame
if (nextFrameIdx == -1)
{
	continue;
}

var frame = interp.Frames[nextFrameIdx];
var ent = (NetEntity)hm;

if (nextFrameIdx != interp.nextFrame)
{
	//Debug.Log("------------------------------");
	interp.fromPosition = pair.Key.Model.Position; // current rendered position
	interp.fromAngles = pair.Key.Model.Angles; // current rendered angles
	interp.toPosition = frame.Position; // state received by server
	interp.toAngles = frame.Angles; // state received by server
	interp.velocity = frame.Velocity; // state received by server
	interp.nextFrame = nextFrameIdx;
	//interp.accumulator = 0;
	interp.startTime = Time.time;
	interp.finishTime = Time.time + updateRate;
}

Debug.DrawLine(interp.fromPosition, interp.fromPosition + Vector3.up * 2, Color.green);
Debug.DrawLine(interp.toPosition, interp.toPosition + Vector3.up * 2, Color.yellow);

//interp.accumulator += Time.deltaTime;
//var t = interp.accumulator / (interp.finishTime - interp.startTime);
var t = (Time.time - interp.startTime) / (interp.finishTime - interp.startTime);
//Debug.Log(t);
var newPos = Vector3.LerpUnclamped(interp.fromPosition, interp.toPosition, t);
var newRot = Quaternion.Lerp(Quaternion.Euler(interp.fromAngles), Quaternion.Euler(interp.toAngles), t);
hm.Model.Set(newPos, newRot.eulerAngles);

 

And here's how it looks, with an update rate of 2 per second:

 

2018-04-14_14-24-02.gif

 

You can see movement velocity varies depending on how far the entity must move.  With a smaller update interval, this becomes less obvious, but there are micro-jitters which I'm looking to get rid of.

 

My other question is about lag compensation.  In my code, each entity has its own accumulator or subframe for interpolation.  Do I have to interpolate all entities simultaneously between global snapshots in order to send the client's subframe to servers to achieve an accurate rewind?

 

edit: Here's a video showing the jitter at various update rates.  Maybe its unrelated to my initial problem?  More update rates gives pretty consistent spacings between point a & b

https://streamable.com/72s2d

 

Edited by Crayz92

Share this post


Link to post
Share on other sites
Advertisement

http://www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8 here you might find possible fix to your problem, when you're using frame / timestamp -dependent movement.

/MODERATOR COMMENT: The link goes to an article about smoothing motion and how to work with timestamps in Unity.  Without any other words nor useful text in the URL, I wasn't sure if I was clicking through to spam or a browser hijacking, or if it was actually related to the discussion.

Edited by wobes
Add note regarding link content.

Share this post


Link to post
Share on other sites
8 hours ago, wobes said:

Useful article, but not related to networking.

 

I fixed up my interp logic a bit.  Had some issues with how I was finding the next frame to transition to, and processing the same position twice (t=1, then t=0 after finding a new frame), however still curious about lag compensation.

Edited by Crayz92

Share this post


Link to post
Share on other sites

This has been covered a lot of times on this forum so do a search and you might find some hints that help you out. :)

Generally speaking there isn't so much one standard way of handling this, but a bunch of broad principles you get to trade-off, depending on what is most important to you - lowest latency, most accurate position, most accurate velocity, etc.

If your system is buffering up updates ('frames'?) and you attempt to keep a buffer of 100 milliseconds (the GetFrameInPast / 0.1f bit?) then the broad logic looks correct, and you shouldn't need extrapolation. However, your system directly lerps towards the next frame's position as soon as the frame changes - this means that velocity will also change instantly at that point as these frame switches will not be at exact and identical millisecond boundaries, and those velocity discontinuities are often visible.

The easiest improvement here is, as you know, to increase the update rate - more updates per second means that these discontinuities will be smaller and less visible. But you can also be careful at the time you switch frames and be careful to handle the timing error. For example, you'll normally switch frames some number of milliseconds early, so you can add that to the next frame duration to balance it out. There are also ways to interpolate velocity rather than position to smooth over these discontinuities - probably easy if your calculus is good, which mine is not. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!