mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
fix(Prediction): ConfigurableJoints' range of motion is now moved correctly
This commit is contained in:
parent
78cdaef9c4
commit
2ed1d7329c
@ -102,6 +102,11 @@ public class PredictedRigidbody : NetworkBehaviour
|
|||||||
// we also create one extra ghost for the exact known server state.
|
// we also create one extra ghost for the exact known server state.
|
||||||
protected GameObject remoteCopy;
|
protected GameObject remoteCopy;
|
||||||
|
|
||||||
|
// joints
|
||||||
|
Vector3 initialPosition;
|
||||||
|
Quaternion initialRotation;
|
||||||
|
Vector3 initialScale;
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
tf = transform;
|
tf = transform;
|
||||||
@ -111,6 +116,11 @@ void Awake()
|
|||||||
// cache some threshold to avoid calculating them in LateUpdate
|
// cache some threshold to avoid calculating them in LateUpdate
|
||||||
float colliderSize = GetComponentInChildren<Collider>().bounds.size.magnitude;
|
float colliderSize = GetComponentInChildren<Collider>().bounds.size.magnitude;
|
||||||
smoothFollowThreshold = colliderSize * teleportDistanceMultiplier;
|
smoothFollowThreshold = colliderSize * teleportDistanceMultiplier;
|
||||||
|
|
||||||
|
// cache initial position/rotation/scale to be used when moving physics components (configurable joints' range of motion)
|
||||||
|
initialPosition = tf.position;
|
||||||
|
initialRotation = tf.rotation;
|
||||||
|
initialScale = tf.localScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void CopyRenderersAsGhost(GameObject destination, Material material)
|
protected virtual void CopyRenderersAsGhost(GameObject destination, Material material)
|
||||||
@ -164,9 +174,6 @@ protected virtual void CreateGhosts()
|
|||||||
// if we copy localScale then the copy has scale=0.5, where as the
|
// if we copy localScale then the copy has scale=0.5, where as the
|
||||||
// original would have a global scale of ~1.0.
|
// original would have a global scale of ~1.0.
|
||||||
physicsCopy = new GameObject($"{name}_Physical");
|
physicsCopy = new GameObject($"{name}_Physical");
|
||||||
physicsCopy.transform.position = tf.position; // world position!
|
|
||||||
physicsCopy.transform.rotation = tf.rotation; // world rotation!
|
|
||||||
physicsCopy.transform.localScale = tf.lossyScale; // world scale!
|
|
||||||
|
|
||||||
// assign the same Layer for the physics copy.
|
// assign the same Layer for the physics copy.
|
||||||
// games may use a custom physics collision matrix, layer matters.
|
// games may use a custom physics collision matrix, layer matters.
|
||||||
@ -176,8 +183,25 @@ protected virtual void CreateGhosts()
|
|||||||
PredictedRigidbodyPhysicsGhost physicsGhostRigidbody = physicsCopy.AddComponent<PredictedRigidbodyPhysicsGhost>();
|
PredictedRigidbodyPhysicsGhost physicsGhostRigidbody = physicsCopy.AddComponent<PredictedRigidbodyPhysicsGhost>();
|
||||||
physicsGhostRigidbody.target = tf;
|
physicsGhostRigidbody.target = tf;
|
||||||
|
|
||||||
// move the rigidbody component & all colliders to the physics GameObject
|
// when moving (Configurable)Joints, their range of motion is
|
||||||
|
// relative to the initial position. if we move them after the
|
||||||
|
// GameObject rotated, the range of motion is wrong.
|
||||||
|
// the easiest solution is to move to initial position,
|
||||||
|
// then move physics components, then move back.
|
||||||
|
// => remember previous
|
||||||
|
Vector3 position = tf.position;
|
||||||
|
Quaternion rotation = tf.rotation;
|
||||||
|
Vector3 scale = tf.localScale;
|
||||||
|
// => reset to initial
|
||||||
|
physicsGhostRigidbody.transform.position = tf.position = initialPosition;
|
||||||
|
physicsGhostRigidbody.transform.rotation = tf.rotation = initialRotation;
|
||||||
|
physicsGhostRigidbody.transform.localScale = tf.localScale = initialScale;
|
||||||
|
// => move physics components
|
||||||
PredictionUtils.MovePhysicsComponents(gameObject, physicsCopy);
|
PredictionUtils.MovePhysicsComponents(gameObject, physicsCopy);
|
||||||
|
// => reset previous
|
||||||
|
physicsGhostRigidbody.transform.position = tf.position = position;
|
||||||
|
physicsGhostRigidbody.transform.rotation = tf.rotation = rotation;
|
||||||
|
physicsGhostRigidbody.transform.localScale = tf.localScale = scale;
|
||||||
|
|
||||||
// show ghost by copying all renderers / materials with ghost material applied
|
// show ghost by copying all renderers / materials with ghost material applied
|
||||||
if (showGhost)
|
if (showGhost)
|
||||||
@ -213,7 +237,27 @@ protected virtual void DestroyGhosts()
|
|||||||
// otherwise next time they wouldn't have a collider anymore.
|
// otherwise next time they wouldn't have a collider anymore.
|
||||||
if (physicsCopy != null)
|
if (physicsCopy != null)
|
||||||
{
|
{
|
||||||
|
// when moving (Configurable)Joints, their range of motion is
|
||||||
|
// relative to the initial position. if we move them after the
|
||||||
|
// GameObject rotated, the range of motion is wrong.
|
||||||
|
// the easiest solution is to move to initial position,
|
||||||
|
// then move physics components, then move back.
|
||||||
|
// => remember previous
|
||||||
|
Vector3 position = tf.position;
|
||||||
|
Quaternion rotation = tf.rotation;
|
||||||
|
Vector3 scale = tf.localScale;
|
||||||
|
// => reset to initial
|
||||||
|
physicsCopy.transform.position = tf.position = initialPosition;
|
||||||
|
physicsCopy.transform.rotation = tf.rotation = initialRotation;
|
||||||
|
physicsCopy.transform.localScale = tf.localScale = initialScale;
|
||||||
|
// => move physics components
|
||||||
PredictionUtils.MovePhysicsComponents(physicsCopy, gameObject);
|
PredictionUtils.MovePhysicsComponents(physicsCopy, gameObject);
|
||||||
|
// => reset previous
|
||||||
|
tf.position = position;
|
||||||
|
tf.rotation = rotation;
|
||||||
|
tf.localScale = scale;
|
||||||
|
|
||||||
|
// when moving components back, we need to undo the joints initial-delta rotation that we added.
|
||||||
Destroy(physicsCopy);
|
Destroy(physicsCopy);
|
||||||
|
|
||||||
// reassign our Rigidbody reference
|
// reassign our Rigidbody reference
|
||||||
|
@ -30,8 +30,12 @@ public static void MoveRigidbody(GameObject source, GameObject destination)
|
|||||||
rigidbodyCopy.constraints = original.constraints;
|
rigidbodyCopy.constraints = original.constraints;
|
||||||
rigidbodyCopy.sleepThreshold = original.sleepThreshold;
|
rigidbodyCopy.sleepThreshold = original.sleepThreshold;
|
||||||
rigidbodyCopy.freezeRotation = original.freezeRotation;
|
rigidbodyCopy.freezeRotation = original.freezeRotation;
|
||||||
rigidbodyCopy.position = original.position;
|
|
||||||
rigidbodyCopy.rotation = original.rotation;
|
// moving (Configurable)Joints messes up their range of motion unless
|
||||||
|
// we reset to initial position first (we do this in PredictedRigibody.cs).
|
||||||
|
// so here we don't set the Rigidbody's physics position at all.
|
||||||
|
// rigidbodyCopy.position = original.position;
|
||||||
|
// rigidbodyCopy.rotation = original.rotation;
|
||||||
|
|
||||||
// projects may keep Rigidbodies as kinematic sometimes. in that case, setting velocity would log an error
|
// projects may keep Rigidbodies as kinematic sometimes. in that case, setting velocity would log an error
|
||||||
if (!original.isKinematic)
|
if (!original.isKinematic)
|
||||||
@ -250,10 +254,10 @@ public static void MoveConfigurableJoints(GameObject source, GameObject destinat
|
|||||||
jointCopy.connectedMassScale = sourceJoint.connectedMassScale;
|
jointCopy.connectedMassScale = sourceJoint.connectedMassScale;
|
||||||
jointCopy.enableCollision = sourceJoint.enableCollision;
|
jointCopy.enableCollision = sourceJoint.enableCollision;
|
||||||
jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing;
|
jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing;
|
||||||
jointCopy.highAngularXLimit = sourceJoint.highAngularXLimit;
|
jointCopy.highAngularXLimit = sourceJoint.highAngularXLimit; // moving this only works if the object is at initial position/rotation/scale, see PredictedRigidbody.cs
|
||||||
jointCopy.linearLimitSpring = sourceJoint.linearLimitSpring;
|
jointCopy.linearLimitSpring = sourceJoint.linearLimitSpring;
|
||||||
jointCopy.linearLimit = sourceJoint.linearLimit;
|
jointCopy.linearLimit = sourceJoint.linearLimit;
|
||||||
jointCopy.lowAngularXLimit = sourceJoint.lowAngularXLimit;
|
jointCopy.lowAngularXLimit = sourceJoint.lowAngularXLimit; // moving this only works if the object is at initial position/rotation/scale, see PredictedRigidbody.cs
|
||||||
jointCopy.massScale = sourceJoint.massScale;
|
jointCopy.massScale = sourceJoint.massScale;
|
||||||
jointCopy.projectionAngle = sourceJoint.projectionAngle;
|
jointCopy.projectionAngle = sourceJoint.projectionAngle;
|
||||||
jointCopy.projectionDistance = sourceJoint.projectionDistance;
|
jointCopy.projectionDistance = sourceJoint.projectionDistance;
|
||||||
|
Loading…
Reference in New Issue
Block a user