420 lines
23 KiB
C#
420 lines
23 KiB
C#
|
// standalone utility functions for PredictedRigidbody component.
|
||
|
using System;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Mirror
|
||
|
{
|
||
|
public static class PredictionUtils
|
||
|
{
|
||
|
// rigidbody ///////////////////////////////////////////////////////////
|
||
|
// move a Rigidbody + settings from one GameObject to another.
|
||
|
public static void MoveRigidbody(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// create a new Rigidbody component on destination.
|
||
|
// note that adding a Joint automatically adds a Rigidbody.
|
||
|
// so first check if one was added yet.
|
||
|
Rigidbody original = source.GetComponent<Rigidbody>();
|
||
|
if (original == null) throw new Exception($"Prediction: attempted to move {source}'s Rigidbody to the predicted copy, but there was no component.");
|
||
|
Rigidbody rigidbodyCopy;
|
||
|
if (!destination.TryGetComponent(out rigidbodyCopy))
|
||
|
rigidbodyCopy = destination.AddComponent<Rigidbody>();
|
||
|
|
||
|
// copy all properties
|
||
|
rigidbodyCopy.mass = original.mass;
|
||
|
rigidbodyCopy.drag = original.drag;
|
||
|
rigidbodyCopy.angularDrag = original.angularDrag;
|
||
|
rigidbodyCopy.useGravity = original.useGravity;
|
||
|
rigidbodyCopy.isKinematic = original.isKinematic;
|
||
|
rigidbodyCopy.interpolation = original.interpolation;
|
||
|
rigidbodyCopy.collisionDetectionMode = original.collisionDetectionMode;
|
||
|
rigidbodyCopy.constraints = original.constraints;
|
||
|
rigidbodyCopy.sleepThreshold = original.sleepThreshold;
|
||
|
rigidbodyCopy.freezeRotation = original.freezeRotation;
|
||
|
|
||
|
// 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
|
||
|
if (!original.isKinematic)
|
||
|
{
|
||
|
rigidbodyCopy.velocity = original.velocity;
|
||
|
rigidbodyCopy.angularVelocity = original.angularVelocity;
|
||
|
}
|
||
|
|
||
|
// destroy original
|
||
|
GameObject.Destroy(original);
|
||
|
}
|
||
|
|
||
|
// helper function: if a collider is on a child, copy that child first.
|
||
|
// this way child's relative position/rotation/scale are preserved.
|
||
|
public static GameObject CopyRelativeTransform(GameObject source, Transform sourceChild, GameObject destination)
|
||
|
{
|
||
|
// is this on the source root? then we want to put it on the destination root.
|
||
|
if (sourceChild == source.transform) return destination;
|
||
|
|
||
|
// is this on a child? then create the same child with the same transform on destination.
|
||
|
// note this is technically only correct for the immediate child since
|
||
|
// .localPosition is relative to parent, but this is good enough.
|
||
|
GameObject child = new GameObject(sourceChild.name);
|
||
|
child.transform.SetParent(destination.transform, true);
|
||
|
child.transform.localPosition = sourceChild.localPosition;
|
||
|
child.transform.localRotation = sourceChild.localRotation;
|
||
|
child.transform.localScale = sourceChild.localScale;
|
||
|
|
||
|
// assign the same Layer for the physics copy.
|
||
|
// games may use a custom physics collision matrix, layer matters.
|
||
|
child.layer = sourceChild.gameObject.layer;
|
||
|
|
||
|
return child;
|
||
|
}
|
||
|
|
||
|
// colliders ///////////////////////////////////////////////////////////
|
||
|
// move all BoxColliders + settings from one GameObject to another.
|
||
|
public static void MoveBoxColliders(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
BoxCollider[] sourceColliders = source.GetComponentsInChildren<BoxCollider>();
|
||
|
foreach (BoxCollider sourceCollider in sourceColliders)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if collider is on root, it returns destination root.
|
||
|
// if collider is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination);
|
||
|
BoxCollider colliderCopy = target.AddComponent<BoxCollider>();
|
||
|
colliderCopy.center = sourceCollider.center;
|
||
|
colliderCopy.size = sourceCollider.size;
|
||
|
colliderCopy.isTrigger = sourceCollider.isTrigger;
|
||
|
colliderCopy.material = sourceCollider.material;
|
||
|
GameObject.Destroy(sourceCollider);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all SphereColliders + settings from one GameObject to another.
|
||
|
public static void MoveSphereColliders(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
SphereCollider[] sourceColliders = source.GetComponentsInChildren<SphereCollider>();
|
||
|
foreach (SphereCollider sourceCollider in sourceColliders)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if collider is on root, it returns destination root.
|
||
|
// if collider is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination);
|
||
|
SphereCollider colliderCopy = target.AddComponent<SphereCollider>();
|
||
|
colliderCopy.center = sourceCollider.center;
|
||
|
colliderCopy.radius = sourceCollider.radius;
|
||
|
colliderCopy.isTrigger = sourceCollider.isTrigger;
|
||
|
colliderCopy.material = sourceCollider.material;
|
||
|
GameObject.Destroy(sourceCollider);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all CapsuleColliders + settings from one GameObject to another.
|
||
|
public static void MoveCapsuleColliders(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
CapsuleCollider[] sourceColliders = source.GetComponentsInChildren<CapsuleCollider>();
|
||
|
foreach (CapsuleCollider sourceCollider in sourceColliders)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if collider is on root, it returns destination root.
|
||
|
// if collider is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination);
|
||
|
CapsuleCollider colliderCopy = target.AddComponent<CapsuleCollider>();
|
||
|
colliderCopy.center = sourceCollider.center;
|
||
|
colliderCopy.radius = sourceCollider.radius;
|
||
|
colliderCopy.height = sourceCollider.height;
|
||
|
colliderCopy.direction = sourceCollider.direction;
|
||
|
colliderCopy.isTrigger = sourceCollider.isTrigger;
|
||
|
colliderCopy.material = sourceCollider.material;
|
||
|
GameObject.Destroy(sourceCollider);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all MeshColliders + settings from one GameObject to another.
|
||
|
public static void MoveMeshColliders(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
MeshCollider[] sourceColliders = source.GetComponentsInChildren<MeshCollider>();
|
||
|
foreach (MeshCollider sourceCollider in sourceColliders)
|
||
|
{
|
||
|
// when Models have Mesh->Read/Write disabled, it means that Unity
|
||
|
// uploads the mesh directly to the GPU and erases it on the CPU.
|
||
|
// on some platforms this makes moving a MeshCollider in builds impossible:
|
||
|
//
|
||
|
// "CollisionMeshData couldn't be created because the mesh has been marked as non-accessible."
|
||
|
//
|
||
|
// on other platforms, this works fine.
|
||
|
// let's show an explicit log message so in case collisions don't
|
||
|
// work at runtime, it's obvious why it happens and how to fix it.
|
||
|
if (!sourceCollider.sharedMesh.isReadable)
|
||
|
{
|
||
|
Debug.Log($"[Prediction]: MeshCollider on {sourceCollider.name} isn't readable, which may indicate that the Mesh only exists on the GPU. If {sourceCollider.name} is missing collisions, then please select the model in the Project Area, and enable Mesh->Read/Write so it's also available on the CPU!");
|
||
|
// don't early return. keep trying, it may work.
|
||
|
}
|
||
|
|
||
|
// copy the relative transform:
|
||
|
// if collider is on root, it returns destination root.
|
||
|
// if collider is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceCollider.transform, destination);
|
||
|
MeshCollider colliderCopy = target.AddComponent<MeshCollider>();
|
||
|
colliderCopy.sharedMesh = sourceCollider.sharedMesh;
|
||
|
colliderCopy.convex = sourceCollider.convex;
|
||
|
colliderCopy.isTrigger = sourceCollider.isTrigger;
|
||
|
colliderCopy.material = sourceCollider.material;
|
||
|
GameObject.Destroy(sourceCollider);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all Colliders + settings from one GameObject to another.
|
||
|
public static void MoveAllColliders(GameObject source, GameObject destination)
|
||
|
{
|
||
|
MoveBoxColliders(source, destination);
|
||
|
MoveSphereColliders(source, destination);
|
||
|
MoveCapsuleColliders(source, destination);
|
||
|
MoveMeshColliders(source, destination);
|
||
|
}
|
||
|
|
||
|
// joints //////////////////////////////////////////////////////////////
|
||
|
// move all CharacterJoints + settings from one GameObject to another.
|
||
|
public static void MoveCharacterJoints(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
CharacterJoint[] sourceJoints = source.GetComponentsInChildren<CharacterJoint>();
|
||
|
foreach (CharacterJoint sourceJoint in sourceJoints)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if joint is on root, it returns destination root.
|
||
|
// if joint is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination);
|
||
|
CharacterJoint jointCopy = target.AddComponent<CharacterJoint>();
|
||
|
// apply settings, in alphabetical order
|
||
|
jointCopy.anchor = sourceJoint.anchor;
|
||
|
jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor;
|
||
|
jointCopy.axis = sourceJoint.axis;
|
||
|
jointCopy.breakForce = sourceJoint.breakForce;
|
||
|
jointCopy.breakTorque = sourceJoint.breakTorque;
|
||
|
jointCopy.connectedAnchor = sourceJoint.connectedAnchor;
|
||
|
jointCopy.connectedBody = sourceJoint.connectedBody;
|
||
|
jointCopy.connectedMassScale = sourceJoint.connectedMassScale;
|
||
|
jointCopy.enableCollision = sourceJoint.enableCollision;
|
||
|
jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing;
|
||
|
jointCopy.enableProjection = sourceJoint.enableProjection;
|
||
|
jointCopy.highTwistLimit = sourceJoint.highTwistLimit;
|
||
|
jointCopy.lowTwistLimit = sourceJoint.lowTwistLimit;
|
||
|
jointCopy.massScale = sourceJoint.massScale;
|
||
|
jointCopy.projectionAngle = sourceJoint.projectionAngle;
|
||
|
jointCopy.projectionDistance = sourceJoint.projectionDistance;
|
||
|
jointCopy.swing1Limit = sourceJoint.swing1Limit;
|
||
|
jointCopy.swing2Limit = sourceJoint.swing2Limit;
|
||
|
jointCopy.swingAxis = sourceJoint.swingAxis;
|
||
|
jointCopy.swingLimitSpring = sourceJoint.swingLimitSpring;
|
||
|
jointCopy.twistLimitSpring = sourceJoint.twistLimitSpring;
|
||
|
#if UNITY_2020_3_OR_NEWER
|
||
|
jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody;
|
||
|
#endif
|
||
|
|
||
|
GameObject.Destroy(sourceJoint);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all ConfigurableJoints + settings from one GameObject to another.
|
||
|
public static void MoveConfigurableJoints(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
ConfigurableJoint[] sourceJoints = source.GetComponentsInChildren<ConfigurableJoint>();
|
||
|
foreach (ConfigurableJoint sourceJoint in sourceJoints)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if joint is on root, it returns destination root.
|
||
|
// if joint is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination);
|
||
|
ConfigurableJoint jointCopy = target.AddComponent<ConfigurableJoint>();
|
||
|
// apply settings, in alphabetical order
|
||
|
jointCopy.anchor = sourceJoint.anchor;
|
||
|
jointCopy.angularXLimitSpring = sourceJoint.angularXLimitSpring;
|
||
|
jointCopy.angularXDrive = sourceJoint.angularXDrive;
|
||
|
jointCopy.angularXMotion = sourceJoint.angularXMotion;
|
||
|
jointCopy.angularYLimit = sourceJoint.angularYLimit;
|
||
|
jointCopy.angularYMotion = sourceJoint.angularYMotion;
|
||
|
jointCopy.angularYZDrive = sourceJoint.angularYZDrive;
|
||
|
jointCopy.angularYZLimitSpring = sourceJoint.angularYZLimitSpring;
|
||
|
jointCopy.angularZLimit = sourceJoint.angularZLimit;
|
||
|
jointCopy.angularZMotion = sourceJoint.angularZMotion;
|
||
|
jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor;
|
||
|
jointCopy.axis = sourceJoint.axis;
|
||
|
jointCopy.breakForce = sourceJoint.breakForce;
|
||
|
jointCopy.breakTorque = sourceJoint.breakTorque;
|
||
|
jointCopy.configuredInWorldSpace = sourceJoint.configuredInWorldSpace;
|
||
|
jointCopy.connectedAnchor = sourceJoint.connectedAnchor;
|
||
|
jointCopy.connectedBody = sourceJoint.connectedBody;
|
||
|
jointCopy.connectedMassScale = sourceJoint.connectedMassScale;
|
||
|
jointCopy.enableCollision = sourceJoint.enableCollision;
|
||
|
jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing;
|
||
|
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.linearLimit = sourceJoint.linearLimit;
|
||
|
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.projectionAngle = sourceJoint.projectionAngle;
|
||
|
jointCopy.projectionDistance = sourceJoint.projectionDistance;
|
||
|
jointCopy.projectionMode = sourceJoint.projectionMode;
|
||
|
jointCopy.rotationDriveMode = sourceJoint.rotationDriveMode;
|
||
|
jointCopy.secondaryAxis = sourceJoint.secondaryAxis;
|
||
|
jointCopy.slerpDrive = sourceJoint.slerpDrive;
|
||
|
jointCopy.swapBodies = sourceJoint.swapBodies;
|
||
|
jointCopy.targetAngularVelocity = sourceJoint.targetAngularVelocity;
|
||
|
jointCopy.targetPosition = sourceJoint.targetPosition;
|
||
|
jointCopy.targetRotation = sourceJoint.targetRotation;
|
||
|
jointCopy.targetVelocity = sourceJoint.targetVelocity;
|
||
|
jointCopy.xDrive = sourceJoint.xDrive;
|
||
|
jointCopy.xMotion = sourceJoint.xMotion;
|
||
|
jointCopy.yDrive = sourceJoint.yDrive;
|
||
|
jointCopy.yMotion = sourceJoint.yMotion;
|
||
|
jointCopy.zDrive = sourceJoint.zDrive;
|
||
|
jointCopy.zMotion = sourceJoint.zMotion;
|
||
|
#if UNITY_2020_3_OR_NEWER
|
||
|
jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody;
|
||
|
#endif
|
||
|
|
||
|
GameObject.Destroy(sourceJoint);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all FixedJoints + settings from one GameObject to another.
|
||
|
public static void MoveFixedJoints(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
FixedJoint[] sourceJoints = source.GetComponentsInChildren<FixedJoint>();
|
||
|
foreach (FixedJoint sourceJoint in sourceJoints)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if joint is on root, it returns destination root.
|
||
|
// if joint is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination);
|
||
|
FixedJoint jointCopy = target.AddComponent<FixedJoint>();
|
||
|
// apply settings, in alphabetical order
|
||
|
jointCopy.anchor = sourceJoint.anchor;
|
||
|
jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor;
|
||
|
jointCopy.axis = sourceJoint.axis;
|
||
|
jointCopy.breakForce = sourceJoint.breakForce;
|
||
|
jointCopy.breakTorque = sourceJoint.breakTorque;
|
||
|
jointCopy.connectedAnchor = sourceJoint.connectedAnchor;
|
||
|
jointCopy.connectedBody = sourceJoint.connectedBody;
|
||
|
jointCopy.connectedMassScale = sourceJoint.connectedMassScale;
|
||
|
jointCopy.enableCollision = sourceJoint.enableCollision;
|
||
|
jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing;
|
||
|
jointCopy.massScale = sourceJoint.massScale;
|
||
|
#if UNITY_2020_3_OR_NEWER
|
||
|
jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody;
|
||
|
#endif
|
||
|
|
||
|
GameObject.Destroy(sourceJoint);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all HingeJoints + settings from one GameObject to another.
|
||
|
public static void MoveHingeJoints(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
HingeJoint[] sourceJoints = source.GetComponentsInChildren<HingeJoint>();
|
||
|
foreach (HingeJoint sourceJoint in sourceJoints)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if joint is on root, it returns destination root.
|
||
|
// if joint is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination);
|
||
|
HingeJoint jointCopy = target.AddComponent<HingeJoint>();
|
||
|
// apply settings, in alphabetical order
|
||
|
jointCopy.anchor = sourceJoint.anchor;
|
||
|
jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor;
|
||
|
jointCopy.axis = sourceJoint.axis;
|
||
|
jointCopy.breakForce = sourceJoint.breakForce;
|
||
|
jointCopy.breakTorque = sourceJoint.breakTorque;
|
||
|
jointCopy.connectedAnchor = sourceJoint.connectedAnchor;
|
||
|
jointCopy.connectedBody = sourceJoint.connectedBody;
|
||
|
jointCopy.connectedMassScale = sourceJoint.connectedMassScale;
|
||
|
jointCopy.enableCollision = sourceJoint.enableCollision;
|
||
|
jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing;
|
||
|
jointCopy.limits = sourceJoint.limits;
|
||
|
jointCopy.massScale = sourceJoint.massScale;
|
||
|
jointCopy.motor = sourceJoint.motor;
|
||
|
jointCopy.spring = sourceJoint.spring;
|
||
|
jointCopy.useLimits = sourceJoint.useLimits;
|
||
|
jointCopy.useMotor = sourceJoint.useMotor;
|
||
|
jointCopy.useSpring = sourceJoint.useSpring;
|
||
|
#if UNITY_2020_3_OR_NEWER
|
||
|
jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody;
|
||
|
#endif
|
||
|
#if UNITY_2022_3_OR_NEWER
|
||
|
jointCopy.extendedLimits = sourceJoint.extendedLimits;
|
||
|
jointCopy.useAcceleration = sourceJoint.useAcceleration;
|
||
|
#endif
|
||
|
|
||
|
GameObject.Destroy(sourceJoint);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all SpringJoints + settings from one GameObject to another.
|
||
|
public static void MoveSpringJoints(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// colliders may be on children
|
||
|
SpringJoint[] sourceJoints = source.GetComponentsInChildren<SpringJoint>();
|
||
|
foreach (SpringJoint sourceJoint in sourceJoints)
|
||
|
{
|
||
|
// copy the relative transform:
|
||
|
// if joint is on root, it returns destination root.
|
||
|
// if joint is on a child, it creates and returns a child on destination.
|
||
|
GameObject target = CopyRelativeTransform(source, sourceJoint.transform, destination);
|
||
|
SpringJoint jointCopy = target.AddComponent<SpringJoint>();
|
||
|
// apply settings, in alphabetical order
|
||
|
jointCopy.anchor = sourceJoint.anchor;
|
||
|
jointCopy.autoConfigureConnectedAnchor = sourceJoint.autoConfigureConnectedAnchor;
|
||
|
jointCopy.axis = sourceJoint.axis;
|
||
|
jointCopy.breakForce = sourceJoint.breakForce;
|
||
|
jointCopy.breakTorque = sourceJoint.breakTorque;
|
||
|
jointCopy.connectedAnchor = sourceJoint.connectedAnchor;
|
||
|
jointCopy.connectedBody = sourceJoint.connectedBody;
|
||
|
jointCopy.connectedMassScale = sourceJoint.connectedMassScale;
|
||
|
jointCopy.damper = sourceJoint.damper;
|
||
|
jointCopy.enableCollision = sourceJoint.enableCollision;
|
||
|
jointCopy.enablePreprocessing = sourceJoint.enablePreprocessing;
|
||
|
jointCopy.massScale = sourceJoint.massScale;
|
||
|
jointCopy.maxDistance = sourceJoint.maxDistance;
|
||
|
jointCopy.minDistance = sourceJoint.minDistance;
|
||
|
jointCopy.spring = sourceJoint.spring;
|
||
|
jointCopy.tolerance = sourceJoint.tolerance;
|
||
|
#if UNITY_2020_3_OR_NEWER
|
||
|
jointCopy.connectedArticulationBody = sourceJoint.connectedArticulationBody;
|
||
|
#endif
|
||
|
|
||
|
GameObject.Destroy(sourceJoint);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// move all Joints + settings from one GameObject to another.
|
||
|
public static void MoveAllJoints(GameObject source, GameObject destination)
|
||
|
{
|
||
|
MoveCharacterJoints(source, destination);
|
||
|
MoveConfigurableJoints(source, destination);
|
||
|
MoveFixedJoints(source, destination);
|
||
|
MoveHingeJoints(source, destination);
|
||
|
MoveSpringJoints(source, destination);
|
||
|
}
|
||
|
|
||
|
// all /////////////////////////////////////////////////////////////////
|
||
|
// move all physics components from one GameObject to another.
|
||
|
public static void MovePhysicsComponents(GameObject source, GameObject destination)
|
||
|
{
|
||
|
// need to move joints first, otherwise we might see:
|
||
|
// 'can't move Rigidbody because a Joint depends on it'
|
||
|
MoveAllJoints(source, destination);
|
||
|
MoveAllColliders(source, destination);
|
||
|
MoveRigidbody(source, destination);
|
||
|
}
|
||
|
}
|
||
|
}
|