mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
ema
This commit is contained in:
parent
68a7365232
commit
a7f2a8fed3
@ -70,8 +70,15 @@ struct PendingForce
|
|||||||
public bool debugColors = false;
|
public bool debugColors = false;
|
||||||
Color originalColor = Color.white;
|
Color originalColor = Color.white;
|
||||||
public Color predictingColor = Color.green;
|
public Color predictingColor = Color.green;
|
||||||
public Color blendingExactColor = Color.yellow;
|
|
||||||
public Color blendingGuessColor = Color.red;
|
public Color blendingGuessColor = Color.red;
|
||||||
|
public Color blendingGuessAvgColor = Color.cyan;
|
||||||
|
|
||||||
|
// FOLLOWING.startPosition guessing.
|
||||||
|
// always average the last 3 positions to smooth out slightl jitter from guessing.
|
||||||
|
// exponential moving average for each float.
|
||||||
|
ExponentialMovingAverage guessXAvg = new ExponentialMovingAverage(3);
|
||||||
|
ExponentialMovingAverage guessYAvg = new ExponentialMovingAverage(3);
|
||||||
|
ExponentialMovingAverage guessZAvg = new ExponentialMovingAverage(3);
|
||||||
|
|
||||||
protected override void Awake()
|
protected override void Awake()
|
||||||
{
|
{
|
||||||
@ -235,6 +242,9 @@ protected void BeginBlending()
|
|||||||
// reset old state
|
// reset old state
|
||||||
followingStartPositionEstimate = null;
|
followingStartPositionEstimate = null;
|
||||||
followingStartRotationEstimate = null;
|
followingStartRotationEstimate = null;
|
||||||
|
guessXAvg.Reset();
|
||||||
|
guessYAvg.Reset();
|
||||||
|
guessZAvg.Reset();
|
||||||
|
|
||||||
// remember exactly where blending started.
|
// remember exactly where blending started.
|
||||||
predictionEndPosition = predictedRigidbody.position;
|
predictionEndPosition = predictedRigidbody.position;
|
||||||
@ -308,6 +318,8 @@ protected override void ApplySnapshot(NTSnapshot interpolated)
|
|||||||
|
|
||||||
Vector3? followingStartPositionEstimate;
|
Vector3? followingStartPositionEstimate;
|
||||||
Quaternion? followingStartRotationEstimate;
|
Quaternion? followingStartRotationEstimate;
|
||||||
|
Vector3 followingStartPositionEstimateAvg =>
|
||||||
|
new Vector3((float)guessXAvg.Value, (float)guessYAvg.Value, (float)guessZAvg.Value);
|
||||||
|
|
||||||
// Prediction uses a Rigidbody, which needs to be moved in FixedUpdate() even while kinematic.
|
// Prediction uses a Rigidbody, which needs to be moved in FixedUpdate() even while kinematic.
|
||||||
double lastReceivedRemoteTime = 0;
|
double lastReceivedRemoteTime = 0;
|
||||||
@ -343,6 +355,12 @@ void UpdateClient()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// debug colors
|
||||||
|
if (debugColors)
|
||||||
|
{
|
||||||
|
rend.material.color = blendingGuessColor;
|
||||||
|
}
|
||||||
|
|
||||||
// first principles:
|
// first principles:
|
||||||
//
|
//
|
||||||
// BLENDING needs to interpolate between PREDICTING & FOLLOWING.
|
// BLENDING needs to interpolate between PREDICTING & FOLLOWING.
|
||||||
@ -360,6 +378,11 @@ void UpdateClient()
|
|||||||
// do we have an estimate yet?
|
// do we have an estimate yet?
|
||||||
if (!followingStartPositionEstimate.HasValue) return;
|
if (!followingStartPositionEstimate.HasValue) return;
|
||||||
|
|
||||||
|
// use the moving average of the last 3 FOLLOWING.startPosition guesses
|
||||||
|
// TODO rotation avg?
|
||||||
|
Vector3 targetPosition = followingStartPositionEstimateAvg;
|
||||||
|
Quaternion targetRotation = followingStartRotationEstimate.Value;
|
||||||
|
|
||||||
// now we have the exact FOLLOW.startPosition, or a best guess.
|
// now we have the exact FOLLOW.startPosition, or a best guess.
|
||||||
// interpolate from where we started to where we are going.
|
// interpolate from where we started to where we are going.
|
||||||
// we started at predictionEndPosition @ blendingStartTime.
|
// we started at predictionEndPosition @ blendingStartTime.
|
||||||
@ -369,11 +392,11 @@ void UpdateClient()
|
|||||||
float blendFactor = totalBlendTime > 0 ? Mathf.Clamp01(elapsedBlendTime / totalBlendTime) : 0; // avoids divide by zero
|
float blendFactor = totalBlendTime > 0 ? Mathf.Clamp01(elapsedBlendTime / totalBlendTime) : 0; // avoids divide by zero
|
||||||
|
|
||||||
// interpolate
|
// interpolate
|
||||||
Vector3 targetPosition = Vector3.Lerp(followingStartPositionEstimate.Value, predictionEndPosition, blendFactor);
|
Vector3 position = Vector3.Lerp(targetPosition, predictionEndPosition, blendFactor);
|
||||||
Quaternion targetRotation = Quaternion.Slerp(followingStartRotationEstimate.Value, predictionEndRotation, blendFactor);
|
Quaternion rotation = Quaternion.Slerp(targetRotation, predictionEndRotation, blendFactor);
|
||||||
|
|
||||||
// set position and rotation
|
// set position and rotation
|
||||||
tf.SetPositionAndRotation(targetPosition, targetRotation);
|
tf.SetPositionAndRotation(position, rotation);
|
||||||
}
|
}
|
||||||
// FOLLOWING sets Transform, which happens in Update().
|
// FOLLOWING sets Transform, which happens in Update().
|
||||||
else if (state == ForecastState.FOLLOWING)
|
else if (state == ForecastState.FOLLOWING)
|
||||||
@ -439,6 +462,9 @@ private void OnDrawGizmos()
|
|||||||
{
|
{
|
||||||
Gizmos.color = blendingGuessColor;
|
Gizmos.color = blendingGuessColor;
|
||||||
Gizmos.DrawWireCube(followingStartPositionEstimate.Value, bounds.size);
|
Gizmos.DrawWireCube(followingStartPositionEstimate.Value, bounds.size);
|
||||||
|
|
||||||
|
Gizmos.color = blendingGuessAvgColor;
|
||||||
|
Gizmos.DrawWireCube(followingStartPositionEstimateAvg, bounds.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,12 +508,6 @@ bool GuessForecastingStartPosition(out Vector3 position, out Quaternion rotation
|
|||||||
position = interpolated.position;
|
position = interpolated.position;
|
||||||
rotation = interpolated.rotation;
|
rotation = interpolated.rotation;
|
||||||
|
|
||||||
// debug colors
|
|
||||||
if (debugColors)
|
|
||||||
{
|
|
||||||
rend.material.color = blendingExactColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// if not, then we need to guess.
|
// if not, then we need to guess.
|
||||||
@ -515,12 +535,6 @@ bool GuessForecastingStartPosition(out Vector3 position, out Quaternion rotation
|
|||||||
position = latest.position + velocity * timeToBlendingEnd;
|
position = latest.position + velocity * timeToBlendingEnd;
|
||||||
rotation = latest.rotation * Quaternion.Slerp(Quaternion.identity, rotationDelta, timeToBlendingEnd / timeDelta);
|
rotation = latest.rotation * Quaternion.Slerp(Quaternion.identity, rotationDelta, timeToBlendingEnd / timeDelta);
|
||||||
|
|
||||||
// debug colors
|
|
||||||
if (debugColors)
|
|
||||||
{
|
|
||||||
rend.material.color = blendingGuessColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// this shouldn't really happen. if timedelta is zero: do nothing.
|
// this shouldn't really happen. if timedelta is zero: do nothing.
|
||||||
@ -561,6 +575,12 @@ protected override void OnServerToClientSync(Vector3? position, Quaternion? rota
|
|||||||
{
|
{
|
||||||
followingStartPositionEstimate = followStartPosition;
|
followingStartPositionEstimate = followStartPosition;
|
||||||
followingStartRotationEstimate = followStartRotation;
|
followingStartRotationEstimate = followStartRotation;
|
||||||
|
|
||||||
|
// average the last 3 guesses to smooth out guess related jitter.
|
||||||
|
// otherwise it's a bit noticable since guesses jump back & forth, and so would the interpolation.
|
||||||
|
guessXAvg.Add(followStartPosition.x);
|
||||||
|
guessYAvg.Add(followStartPosition.y);
|
||||||
|
guessZAvg.Add(followStartPosition.z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user