From ba16e2f949f8aa643c9bf5f6e2020a8fb2a899ee Mon Sep 17 00:00:00 2001 From: mischa Date: Mon, 8 Jan 2024 11:33:31 +0100 Subject: [PATCH] fix(PredictedRigidbody): now snaps into place below a velocity threshold to fix dancing rigidbodies near rest position due to prediction fighting with corrections --- .../PredictedRigidbody/PredictedRigidbody.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs index ec2028893..eeb148c0c 100644 --- a/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs +++ b/Assets/Mirror/Components/PredictedRigidbody/PredictedRigidbody.cs @@ -85,6 +85,9 @@ public class PredictedRigidbody : NetworkBehaviour [Tooltip("Configure how to apply the corrected state.")] public CorrectionMode correctionMode = CorrectionMode.Move; + [Tooltip("Server & Client would sometimes fight over the final position at rest. Instead, hard snap into black below a certain velocity threshold.")] + public float snapThreshold = 2; + [Header("Visual Interpolation")] [Tooltip("After creating the visual interpolation object, keep showing the original Rigidbody with a ghost (transparent) material for debugging.")] public bool showGhost = true; @@ -332,6 +335,19 @@ void ApplyCorrection(RigidbodyState corrected, RigidbodyState before, RigidbodyS // TODO don't hardcode length? Debug.DrawLine(corrected.position, corrected.position + corrected.velocity * 0.1f, Color.white, lineTime); + // fix rigidbodies seemingly dancing in place instead of coming to rest. + // hard snap to the position below a threshold velocity. + // this is fine because the visual object still smoothly interpolates to it. + if (rb.velocity.magnitude <= snapThreshold) + { + Debug.Log($"Prediction: snapped {name} into place because velocity {rb.velocity.magnitude:F3} <= {snapThreshold:F3}"); + stateHistory.Clear(); + rb.position = corrected.position; + rb.rotation = corrected.rotation; + rb.velocity = Vector3.zero; + return; + } + // now go through the history: // 1. skip all states before the inserted / corrected entry // 3. apply all deltas after timestamp