Example #1
0
        /// <summary>
        /// NB! Make sure to call this from FixedUpdate!
        /// Creates a new muscle for the specified "joint" and targets it to the "target". The joint will be connected to the specified "connectTo" Muscle.
        /// Note that the joint will be binded to it's current position and rotation relative to the "connectTo", so make sure the added object is positioned correctly when calling this.
        /// This method allocates memory, avoid using it each frame.
        /// </summary>
        public void AddMuscle(ConfigurableJoint joint, Transform target, Rigidbody connectTo, Transform targetParent, Muscle.Props muscleProps = null, bool forceTreeHierarchy = false, bool forceLayers = true)
        {
            if (!CheckIfInitiated())
            {
                return;
            }

            if (!initiated)
            {
                Debug.LogWarning("PuppetMaster has not been initiated.", transform);
                return;
            }

            if (ContainsJoint(joint))
            {
                Debug.LogWarning("Joint " + joint.name + " is already used by a Muscle", transform);
                return;
            }

            if (target == null)
            {
                Debug.LogWarning("AddMuscle was called with a null 'target' reference.", transform);
                return;
            }

            if (connectTo == joint.GetComponent <Rigidbody>())
            {
                Debug.LogWarning("ConnectTo is the joint's own Rigidbody, can not add muscle.", transform);
                return;
            }

            if (!isActive)
            {
                Debug.LogWarning("Adding muscles to inactive PuppetMasters is not currently supported.", transform);
                return;
            }

            if (muscleProps == null)
            {
                muscleProps = new Muscle.Props();
            }

            Muscle muscle = new Muscle();

            muscle.props  = muscleProps;
            muscle.joint  = joint;
            muscle.target = target;
            muscle.joint.transform.parent = (hierarchyIsFlat || connectTo == null) && !forceTreeHierarchy? transform: connectTo.transform;

            if (forceLayers)
            {
                joint.gameObject.layer  = gameObject.layer;                //@todo what if collider is on a child gameobject?
                target.gameObject.layer = targetRoot.gameObject.layer;
            }

            if (connectTo != null)
            {
                muscle.target.parent = targetParent;

                Vector3    relativePosition = GetMuscle(connectTo).transform.InverseTransformPoint(muscle.target.position);
                Quaternion relativeRotation = Quaternion.Inverse(GetMuscle(connectTo).transform.rotation) * muscle.target.rotation;

                joint.transform.position = connectTo.transform.TransformPoint(relativePosition);
                joint.transform.rotation = connectTo.transform.rotation * relativeRotation;

                joint.connectedBody = connectTo;
            }

            muscle.Initiate(muscles);

            if (connectTo != null)
            {
                muscle.rigidbody.velocity        = connectTo.velocity;
                muscle.rigidbody.angularVelocity = connectTo.angularVelocity;
            }

            // Ignore internal collisions
            if (!internalCollisions)
            {
                for (int i = 0; i < muscles.Length; i++)
                {
                    muscle.IgnoreCollisions(muscles[i], true);
                }
            }

            Array.Resize(ref muscles, muscles.Length + 1);
            muscles[muscles.Length - 1] = muscle;

            // Update angular limit ignoring
            muscle.IgnoreAngularLimits(!angularLimits);

            if (behaviours.Length > 0)
            {
                muscle.broadcaster = muscle.joint.gameObject.AddComponent <MuscleCollisionBroadcaster>();
                muscle.broadcaster.puppetMaster = this;
                muscle.broadcaster.muscleIndex  = muscles.Length - 1;
            }

            muscle.jointBreakBroadcaster = muscle.joint.gameObject.AddComponent <JointBreakBroadcaster>();
            muscle.jointBreakBroadcaster.puppetMaster = this;
            muscle.jointBreakBroadcaster.muscleIndex  = muscles.Length - 1;

            UpdateHierarchies();
            CheckMassVariation(100f, true);

            foreach (BehaviourBase b in behaviours)
            {
                b.OnMuscleAdded(muscle);
            }
        }
Example #2
0
        /// <summary>
        /// Adds a PropMuscle to the puppet at runtime. If Vector3.zero passed for additionalPinOffset, additional pin will not be added.
        /// </summary>
        public bool AddPropMuscle(ConfigurableJoint addPropMuscleTo, Vector3 position, Quaternion rotation, Vector3 additionalPinOffset, Transform targetParent = null, PuppetMasterProp initiateWithProp = null)
        {
            if (!initiated)
            {
                Debug.LogError("Can not add Prop Muscle to PuppetMaster that has not been initiated! Please use Start() instead of Awake() or PuppetMaster.OnPostInitiate delegate to call AddPropMuscle.", transform);
                return(false);
            }

            if (addPropMuscleTo != null)
            {
                bool isFlat = HierarchyIsFlat();

                var addToMuscle = GetMuscle(addPropMuscleTo);
                if (addToMuscle != null)
                {
                    GameObject go = new GameObject("Prop Muscle " + addPropMuscleTo.name);
                    go.layer              = addPropMuscleTo.gameObject.layer;
                    go.transform.parent   = isFlat ? transform : addPropMuscleTo.transform;
                    go.transform.position = position;
                    go.transform.rotation = rotation;

                    go.AddComponent <Rigidbody>();

                    GameObject target = new GameObject("Prop Muscle Target " + addPropMuscleTo.name);
                    target.gameObject.layer   = addToMuscle.target.gameObject.layer;
                    target.transform.parent   = targetParent != null? targetParent: addToMuscle.target;
                    target.transform.position = go.transform.position;
                    target.transform.rotation = go.transform.rotation;

                    ConfigurableJoint joint = go.AddComponent <ConfigurableJoint>();
                    joint.xMotion        = ConfigurableJointMotion.Locked;
                    joint.yMotion        = ConfigurableJointMotion.Locked;
                    joint.zMotion        = ConfigurableJointMotion.Locked;
                    joint.angularXMotion = ConfigurableJointMotion.Locked;
                    joint.angularYMotion = ConfigurableJointMotion.Locked;
                    joint.angularZMotion = ConfigurableJointMotion.Locked;

                    Muscle.Props props = new Muscle.Props();
                    props.group = Muscle.Group.Prop;

                    AddMuscle(joint, target.transform, addPropMuscleTo.GetComponent <Rigidbody>(), targetParent != null ? targetParent : addToMuscle.target, props, false, true);

                    muscles[muscles.Length - 1].isPropMuscle = true;

                    var propMuscle = go.AddComponent <PropMuscle>();
                    propMuscle.puppetMaster        = this;
                    propMuscle.additionalPinOffset = additionalPinOffset;
                    propMuscle.currentProp         = initiateWithProp;
                    if (additionalPinOffset != Vector3.zero)
                    {
                        propMuscle.AddAdditionalPin();
                    }

                    Array.Resize(ref propMuscles, propMuscles.Length + 1);
                    propMuscles[propMuscles.Length - 1] = propMuscle;
                    propMuscle.OnInitiate();

                    return(true);
                }
                else
                {
                    Debug.LogError("Can't add Prop Muscle to a ConfigurableJoint that is not in the list of PuppetMaster.muscles.", transform);
                    return(false);
                }
            }
            else
            {
                Debug.LogError("Please assign the ConfigurableJoint of the muscle you wish to add the Prop Muscle to.", transform);
                return(false);
            }
        }