diff --git a/Assets/Mirror/Components/ForecastRigidbody/ForecastRigidbody.cs b/Assets/Mirror/Components/ForecastRigidbody/ForecastRigidbody.cs index 940634a1c..7f7995865 100644 --- a/Assets/Mirror/Components/ForecastRigidbody/ForecastRigidbody.cs +++ b/Assets/Mirror/Components/ForecastRigidbody/ForecastRigidbody.cs @@ -85,7 +85,6 @@ public class ForecastRigidbody : NetworkBehaviour public Color predictingColor = Color.green; public Color blendingColor = Color.yellow; - protected virtual void Awake() { tf = transform; @@ -119,8 +118,13 @@ public override void OnStartClient() public void AddPredictedForce(Vector3 force, ForceMode mode) { // explicitly start predicting physics - predictedRigidbody.isKinematic = false; + BeginPredicting(); predictedRigidbody.AddForce(force, mode); + } + + protected void BeginPredicting() + { + predictedRigidbody.isKinematic = false; state = ForecastState.PREDICT; if (debugColors) rend.material.color = predictingColor; OnBeginPrediction(); @@ -216,6 +220,26 @@ void FixedUpdate() RecordState(); } + // while predicting on client, if we hit another object then we need to + // start predicting this one too. + // otherwise the collision response would be delayed until next server + // state to follow comes in. + [ClientCallback] + void OnCollisionEnter(Collision collision) + { + // if we are FOLLOWING, then there's nothing to do. + if (state == ForecastState.FOLLOW) return; + + // is the other object a ForecastRigidbody? + if (!collision.collider.TryGetComponent(out ForecastRigidbody other)) return; + + // is the other object already predicting? then don't call events again. + if (other.state != ForecastState.FOLLOW) return; + + // start predicting the other object too. + other.BeginPredicting(); + } + // manually store last recorded so we can easily check against this // without traversing the SortedList. RigidbodyState lastRecorded; diff --git a/ProjectSettings/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset index 78992f08c..4d39b8a82 100644 --- a/ProjectSettings/DynamicsManager.asset +++ b/ProjectSettings/DynamicsManager.asset @@ -3,10 +3,11 @@ --- !u!55 &1 PhysicsManager: m_ObjectHideFlags: 0 - serializedVersion: 7 + serializedVersion: 13 m_Gravity: {x: 0, y: -9.81, z: 0} m_DefaultMaterial: {fileID: 0} m_BounceThreshold: 2 + m_DefaultMaxDepenetrationVelocity: 10 m_SleepThreshold: 0.005 m_DefaultContactOffset: 0.01 m_DefaultSolverIterations: 6 @@ -20,10 +21,18 @@ PhysicsManager: m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff m_AutoSimulation: 1 m_AutoSyncTransforms: 1 + m_ReuseCollisionCallbacks: 0 m_ClothInterCollisionSettingsToggle: 0 - m_ContactPairsMode: 0 + m_ClothGravity: {x: 0, y: -9.81, z: 0} + m_ContactPairsMode: 1 m_BroadphaseType: 0 m_WorldBounds: m_Center: {x: 0, y: 0, z: 0} m_Extent: {x: 250, y: 250, z: 250} m_WorldSubdivisions: 8 + m_FrictionType: 0 + m_EnableEnhancedDeterminism: 0 + m_EnableUnifiedHeightmaps: 1 + m_ImprovedPatchFriction: 0 + m_SolverType: 0 + m_DefaultMaxAngularSpeed: 7