This commit is contained in:
mischa 2024-02-11 16:57:57 +01:00
parent 07545b9ea0
commit a9d0ff9163

View File

@ -27,8 +27,15 @@ public class PredictedRigidbody : NetworkBehaviour
protected Rigidbody predictedRigidbody; // always valid, even while moved onto the ghost. protected Rigidbody predictedRigidbody; // always valid, even while moved onto the ghost.
Vector3 lastPosition; Vector3 lastPosition;
// [Tooltip("Broadcast changes if position changed by more than ... meters.")] // motion smoothing happen on-demand, because it requires moving physics components to another GameObject.
// public float positionSensitivity = 0.01f; // this only starts at a given velocity and ends when stopped moving.
// to avoid constant on/off/on effects, it also stays on for a minimum time.
[Header("Motion Smoothing")]
[Tooltip("Smoothing via Ghost-following only happens on demand, while moving with a minimum velocity.")]
public float motionSmoothingVelocityThreshold = 0.1f;
public float motionSmoothingAngularVelocityThreshold = 0.1f;
public float motionSmoothingMinimumTime = 0.5f;
double motionSmoothingStartTime;
// client keeps state history for correction & reconciliation. // client keeps state history for correction & reconciliation.
// this needs to be a SortedList because we need to be able to insert inbetween. // this needs to be a SortedList because we need to be able to insert inbetween.
@ -165,6 +172,9 @@ protected virtual void CreateGhosts()
// games may use a custom physics collision matrix, layer matters. // games may use a custom physics collision matrix, layer matters.
physicsCopy.layer = gameObject.layer; physicsCopy.layer = gameObject.layer;
// add the PredictedRigidbodyPhysical component
PredictedRigidbodyPhysicsGhost physicsGhostRigidbody = physicsCopy.AddComponent<PredictedRigidbodyPhysicsGhost>();
physicsGhostRigidbody.target = tf;
// move the rigidbody component & all colliders to the physics GameObject // move the rigidbody component & all colliders to the physics GameObject
PredictionUtils.MovePhysicsComponents(gameObject, physicsCopy); PredictionUtils.MovePhysicsComponents(gameObject, physicsCopy);
@ -305,6 +315,11 @@ void UpdateServer()
SetDirty(); SetDirty();
} }
// movement detection is virtual, in case projects want to use other methods.
protected virtual bool IsMoving() =>
predictedRigidbody.velocity.magnitude >= motionSmoothingVelocityThreshold ||
predictedRigidbody.angularVelocity.magnitude >= motionSmoothingAngularVelocityThreshold;
void UpdateGhosting() void UpdateGhosting()
{ {
// client only uses ghosts on demand while interacting. // client only uses ghosts on demand while interacting.
@ -315,8 +330,9 @@ void UpdateGhosting()
{ {
// faster than velocity threshold? then create the ghosts. // faster than velocity threshold? then create the ghosts.
// with 10% buffer zone so we don't flip flop all the time. // with 10% buffer zone so we don't flip flop all the time.
if (predictedRigidbody.velocity.magnitude >= ghostVelocityThreshold * 1.1f) if (IsMoving())
{ {
motionSmoothingStartTime = NetworkTime.time;
CreateGhosts(); CreateGhosts();
OnBeginPrediction(); OnBeginPrediction();
} }
@ -325,11 +341,12 @@ void UpdateGhosting()
else else
{ {
// slower than velocity threshold? then destroy the ghosts. // slower than velocity threshold? then destroy the ghosts.
// with 10% buffer zone so we don't flip flop all the time. // with a minimum time since starting to move, to avoid on/off/on effects.
if (predictedRigidbody.velocity.magnitude <= ghostVelocityThreshold * 0.9f) if (!IsMoving() && NetworkTime.time >= motionSmoothingStartTime + motionSmoothingMinimumTime)
{ {
DestroyGhosts(); DestroyGhosts();
OnEndPrediction(); OnEndPrediction();
physicsCopy = null; // TESTING
} }
} }
} }