blending ahead/behind debug draw

This commit is contained in:
mischa 2024-04-02 23:11:25 +08:00
parent 8cf073fe5b
commit 7b50aa0271

View File

@ -93,7 +93,8 @@ public class ForecastRigidbody : NetworkBehaviour
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 blendingColor = Color.yellow; public Color blendingBehindColor = Color.gray; // when trying to blend but it's still behind us so we ignore it to not jitter
public Color blendingAheadColor = Color.yellow; // when actually interpolating towards a blend in front of us
protected virtual void Awake() protected virtual void Awake()
{ {
@ -153,7 +154,7 @@ protected void BeginPredicting()
protected void BeginBlending() protected void BeginBlending()
{ {
state = ForecastState.BLENDING; state = ForecastState.BLENDING;
if (debugColors) rend.material.color = blendingColor; // if (debugColors) rend.material.color = blendingAheadColor; set in update depending on ahead/behind
blendingStartTime = NetworkTime.time; blendingStartTime = NetworkTime.time;
OnBeginBlending(); OnBeginBlending();
Debug.Log($"{name} BEGIN BLENDING"); Debug.Log($"{name} BEGIN BLENDING");
@ -201,6 +202,18 @@ protected virtual bool IsMoving() =>
predictedRigidbody.velocity.sqrMagnitude >= motionSmoothingVelocityThresholdSqr || predictedRigidbody.velocity.sqrMagnitude >= motionSmoothingVelocityThresholdSqr ||
predictedRigidbody.angularVelocity.sqrMagnitude >= motionSmoothingAngularVelocityThresholdSqr; predictedRigidbody.angularVelocity.sqrMagnitude >= motionSmoothingAngularVelocityThresholdSqr;
// check if following the remote state would move us backwards, or forward.
// we never want to interpolate backwards.
bool RemoteInSameDirection()
{
Vector3 direction = lastReceivedState.position - transform.position;
// is this in the direction we are going, or behind us (the opposite)?
bool opposite = Vector3.Dot(direction, predictedRigidbody.velocity) < 0;
return !opposite;
}
// when using Fast mode, we don't create any ghosts. // when using Fast mode, we don't create any ghosts.
// but we still want to check IsMoving() in order to support the same // but we still want to check IsMoving() in order to support the same
// user callbacks. // user callbacks.
@ -222,7 +235,6 @@ void UpdateClient()
// FAST VERSION: this shows in profiler a lot, so cache EVERYTHING! // FAST VERSION: this shows in profiler a lot, so cache EVERYTHING!
tf.GetPositionAndRotation(out Vector3 currentPosition, out Quaternion currentRotation); // faster than tf.position + tf.rotation tf.GetPositionAndRotation(out Vector3 currentPosition, out Quaternion currentRotation); // faster than tf.position + tf.rotation
float distance = Vector3.Distance(currentPosition, lastReceivedState.position);
// perf: only access deltaTime once // perf: only access deltaTime once
float deltaTime = Time.deltaTime; float deltaTime = Time.deltaTime;
@ -232,6 +244,7 @@ void UpdateClient()
// => speed increases by distance² because the further away, the // => speed increases by distance² because the further away, the
// sooner we need to catch the fuck up // sooner we need to catch the fuck up
// float positionStep = (distance * distance) * interpolationSpeed; // float positionStep = (distance * distance) * interpolationSpeed;
float distance = Vector3.Distance(currentPosition, lastReceivedState.position);
float positionStep = distance * positionBlendingSpeed * deltaTime; float positionStep = distance * positionBlendingSpeed * deltaTime;
Vector3 newPosition = Vector3.MoveTowards(currentPosition, lastReceivedState.position, positionStep); Vector3 newPosition = Vector3.MoveTowards(currentPosition, lastReceivedState.position, positionStep);
@ -240,22 +253,40 @@ void UpdateClient()
// Quaternions always need to be normalized in order to be a valid rotation after operations // Quaternions always need to be normalized in order to be a valid rotation after operations
Quaternion newRotation = Quaternion.Slerp(currentRotation, lastReceivedState.rotation, rotationBlendingSpeed * deltaTime).normalized; Quaternion newRotation = Quaternion.Slerp(currentRotation, lastReceivedState.rotation, rotationBlendingSpeed * deltaTime).normalized;
// debug draw the blending data. if (!RemoteInSameDirection())
// server state is drawn in OnGizmos {
Debug.DrawLine(currentPosition, newPosition, blendingColor); // debug draw the delta that we aren't using yet
// server state is drawn in OnGizmos
if (debugColors)
{
Debug.DrawLine(currentPosition, newPosition, blendingBehindColor);
rend.material.color = blendingBehindColor;
}
}
else
{
// debug draw the blending data.
// server state is drawn in OnGizmos
if (debugColors)
{
Debug.DrawLine(currentPosition, newPosition, blendingAheadColor);
rend.material.color = blendingAheadColor;
}
// assign position and rotation together. faster than accessing manually. // assign position and rotation together. faster than accessing manually.
tf.SetPositionAndRotation(newPosition, newRotation); tf.SetPositionAndRotation(newPosition, newRotation);
// blend for 2 x syncinterval. // blend for 2 x syncinterval.
// TODO configurable // TODO configurable
// if (NetworkTime.time > blendingStartTime + blendTime) // if (NetworkTime.time > blendingStartTime + blendTime)
// { // {
// BeginFollow(); // BeginFollow();
// } // }
// TODO blend until what.. ? // TODO blend until what.. ?
// maybe until we reached it..? // maybe until we reached it..?
}
} }
else if (state == ForecastState.FOLLOWING) else if (state == ForecastState.FOLLOWING)
{ {
@ -307,7 +338,7 @@ void OnDrawGizmos()
// draw server state while blending // draw server state while blending
if (state == ForecastState.BLENDING) if (state == ForecastState.BLENDING)
{ {
Gizmos.color = blendingColor; Gizmos.color = RemoteInSameDirection() ? blendingAheadColor : blendingBehindColor;
Gizmos.DrawWireCube(lastReceivedState.position, col.bounds.size); Gizmos.DrawWireCube(lastReceivedState.position, col.bounds.size);
} }
} }