Пример #1
0
        void RepairBone(RagdollTransform bone)
        {
            if (bone == null)
            {
                return;
            }

            bool isFollow = bone.joint == null;

            // if (!isFollow) {
            //     bone.transform.localRotation = bone.originalRotation;
            //     bone.transform.localPosition = bone.originalPosition;
            //     bone.SetKinematic(false);
            // }

            bone.transform.localScale = Vector3.one;

            if (!isFollow)
            {
                // bone.joint.connectedBody = bone.connectedBody;
                // bone.collider.isTrigger = false;
                bone.collider.gameObject.layer = Ragdoll.layer;

                if (bone.followTarget != null)
                {
                    RepairBone(bone.followTarget);
                }
            }
        }
        /*
         *              ignore collisions with other physics bones on the same ragdoll
         */
        public void IgnoreSelfCollisions(bool ignore)
        {
            if (CheckForErroredRagdoll("IgnoreSelfCollisions"))
            {
                return;
            }

            for (int i = 0; i < bonesCount; i++)
            {
                RagdollTransform boneA = allElements[i];

                for (int x = i + 1; x < bonesCount; x++)
                {
                    RagdollTransform boneB = allElements[x];

                    // dont handle connected joints, joint component already does
                    if (boneB.joint && boneB.joint.connectedBody == boneA.rigidbody)
                    {
                        continue;
                    }
                    if (boneA.joint && boneA.joint.connectedBody == boneB.rigidbody)
                    {
                        continue;
                    }

                    Physics.IgnoreCollision(boneA.collider, boneB.collider, ignore);
                }
            }
        }
Пример #3
0
        static Bounds GetBoxBounds(RagdollTransform bone, RagdollTransform topCutoff, RagdollTransform[] encapsulate, bool adjustMin)
        {
            Bounds bounds = new Bounds();

            //encapsulate upper arms and upper legs positions
            for (int i = 0; i < 4; i++)
            {
                bounds.Encapsulate(bone.transform.InverseTransformPoint(encapsulate[i].transform.position));
            }

            if (adjustMin)
            {
                Vector3 min = bounds.min;
                min.y      = 0;
                bounds.min = min;
            }

            //adjust max bounds based on next bone
            Vector3 max = bounds.max;

            max.y = bone.transform.InverseTransformPoint(topCutoff.transform.position).y;

            bounds.max = max;
            return(bounds);
        }
Пример #4
0
        /*
         *      Set the bone's configurable joint target to the master local rotation
         */
        void HandleJointFollow(RagdollTransform bone, float torque, int boneIndex)
        {
            if (!bone.joint)
            {
                return;
            }

            if (bone.joint.angularXMotion == ConfigurableJointMotion.Locked)
            {
                return;
            }

            //setting joint torque every frame was slow, so check here if its changed
            if (torque != lastTorques[boneIndex])
            {
                lastTorques[boneIndex] = torque;

                jointDrive.positionSpring = torque;
                bone.joint.slerpDrive     = jointDrive;
            }

            //set joints target rotation
            if (torque != 0)
            {
                Quaternion targetLocalRotation = bone.followTarget.transform.localRotation;
                bone.joint.targetRotation = localToJointSpaces[boneIndex] * Quaternion.Inverse(targetLocalRotation) * startLocalRotations[boneIndex];
            }
        }
Пример #5
0
        /*
         *  delay the dismemberment for a few frames in order for physics exerted on the bone
         *  to play out before we disable it
         */

        IEnumerator DismemberBoneDelayed(Ragdoll ragdoll, RagdollTransform bone)
        {
            for (int i = 0; i < ragdoll.ragdollProfile.dismemberBoneFrameDelay; i++)
            {
                yield return(new WaitForFixedUpdate());
            }
            DismemberBone(ragdoll, bone, false);
        }
Пример #6
0
 /*
  *  delay the dismemberment for a few frames in order for physics exerted on the bone
  *  to play out before we disable it
  */
 IEnumerator DismemberBoneDelayed(Ragdoll ragdoll, RagdollTransform bone, int delay)
 {
     for (int i = 0; i < delay; i++)
     {
         yield return(new WaitForFixedUpdate());
     }
     DismemberBone(ragdoll, bone, 0, false);
 }
Пример #7
0
        static Collider AddBoxCollider(RagdollTransform bone, Bounds bounds)
        {
            BoxCollider box = bone.AddComponent <BoxCollider>();

            box.center = bounds.center;
            box.size   = bounds.size;
            return(box);
        }
        public void LoadSnapshot(float snapshotBlend, bool useFollowTarget)
        {
            RagdollTransform element = useFollowTarget && followTarget != null ? followTarget : this;

            TeleportTo(
                Vector3.Lerp(element.transform.position, snapshotPosition, snapshotBlend),
                Quaternion.Slerp(element.GetRotation(), snapshotRotation, snapshotBlend)
                );
        }
Пример #9
0
        public void DismemberBone(Ragdoll ragdoll, RagdollTransform bone, bool isFollowBone)
        {
            if (!isFollowBone)
            {
                bone.collider.gameObject.layer = LayerMask.NameToLayer(ignorePhysicsLayer);

                // bone.joint.connectedBody = null;
                // bone.collider.isTrigger = true;
                // bone.SetKinematic(true);
            }
            bone.transform.localScale = Vector3.one * dismemberScale;
        }
Пример #10
0
        static void AddBreastColliders(Dictionary <HumanBodyBones, RagdollTransform> bones)
        {
            RagdollTransform[] encapsulate = new RagdollTransform[] {
                bones[HumanBodyBones.LeftUpperArm], bones[HumanBodyBones.RightUpperArm],
                bones[HumanBodyBones.LeftUpperLeg], bones[HumanBodyBones.RightUpperLeg],
            };
            RagdollTransform hips  = bones[HumanBodyBones.Hips];
            RagdollTransform chest = bones[HumanBodyBones.Chest];
            RagdollTransform head  = bones[HumanBodyBones.Head];

            hips.collider  = AddBoxCollider(hips, GetBoxBounds(hips, chest, encapsulate, false));
            chest.collider = AddBoxCollider(chest, GetBoxBounds(chest, head, encapsulate, true));
        }
Пример #11
0
        void InitializeVelocitySetValues()
        {
            animationVelocityTrackers = new VelocityTracker[Ragdoll.bonesCount];

            for (int i = 0; i < Ragdoll.bonesCount; i++)
            {
                RagdollTransform bone = ragdoll.GetBone(Ragdoll.humanBones[i]);

                //track position (offset by ragdoll bone's rigidbody centor of mass) of the follow target
                Vector3 massCenterOffset = bone.transform.InverseTransformPoint(bone.rigidbody.worldCenterOfMass);
                animationVelocityTrackers[i] = new VelocityTracker(bone.followTarget.transform, massCenterOffset);
            }
        }
Пример #12
0
        public void DismemberBone(Ragdoll ragdoll, RagdollTransform bone, int delay, bool isFollowBone = false)
        {
            InitializeDismemberedBones();

            if (!isFollowBone)
            {
                if (!dismemberableBones.Contains(bone.bone.bone))
                {
                    return;
                }

                if (delay > 0)
                {
                    ragdoll.StartCoroutine(DismemberBoneDelayed(ragdoll, bone, delay));
                    return;
                }

                dismemberedBones[bone.bone.bone] = bone;

                bone.collider.gameObject.layer = LayerMask.NameToLayer(ignorePhysicsLayer);

                // bone.joint.connectedBody = null;
                // bone.collider.isTrigger = true;
                // bone.SetKinematic(true);



                // dismember the follow target, so it reflects our dismemberment
                // (dismembers the animated model...)
                if (bone.followTarget != null)
                {
                    DismemberBone(ragdoll, bone.followTarget, 0, true);
                }

                // dismember and disable any child bones (helps physics from getting all jittery)
                HumanBodyBones childBone = Ragdoll.GetChildBone(bone.bone.bone);
                if (childBone != HumanBodyBones.Hips)
                {
                    RagdollTransform childBoneTransform = ragdoll.GetBone(childBone);
                    if (!BoneDismembered(childBoneTransform))
                    {
                        DismemberBone(ragdoll, childBoneTransform, 0, false);
                    }
                }
            }

            bone.transform.localScale = Vector3.one * dismemberScale;
        }
Пример #13
0
        static void BuildCapsules(Dictionary <HumanBodyBones, RagdollTransform> bones)
        {
            foreach (var k in capsuleBones)
            {
                RagdollTransform bone = bones[k];

                int direction = k.ToString().Contains("Arm") ? 0 : 1;

                float distance;
                if (upperCapsuleBones.Contains(k))
                {
                    distance = bone.transform.InverseTransformPoint(bones[Ragdoll.GetChildBone(k)].transform.position)[direction];
                }
                else
                {
                    Vector3 endPoint = (bone.transform.position - bones[Ragdoll.GetParentBone(k)].transform.position) + bone.transform.position;
                    distance = bone.transform.InverseTransformPoint(endPoint)[direction];

                    if (bone.transform.GetComponentsInChildren(typeof(Transform)).Length > 1)
                    {
                        Bounds bounds = new Bounds();
                        foreach (Transform child in bone.transform.GetComponentsInChildren(typeof(Transform)))
                        {
                            bounds.Encapsulate(bone.transform.InverseTransformPoint(child.position));
                        }

                        if (distance > 0)
                        {
                            distance = bounds.max[direction];
                        }
                        else
                        {
                            distance = bounds.min[direction];
                        }
                    }
                }

                CapsuleCollider collider = bone.AddComponent <CapsuleCollider>();
                collider.direction = direction;

                Vector3 center = Vector3.zero;
                center[direction] = distance * 0.5F;
                collider.center   = center;

                collider.height = Mathf.Abs(distance);
                bone.collider   = collider;
            }
        }
        public bool Transform2HumanBone(Transform transform, out RagdollTransform bone)
        {
            bone = null;
            if (CheckForErroredRagdoll("Transform2HumanBone"))
            {
                return(false);
            }

            for (int i = 0; i < bonesCount; i++)
            {
                if (allElements[i].transform == transform)
                {
                    bone = allElements[i];
                    return(true);
                }
            }
            return(false);
        }
Пример #15
0
        /*
         *              Adjust Ragdoll component values per bone to reflect the supplied
         *              Ragdoll profile (default profile if none is supplied)
         */
        public static void UpdateBonesToProfileValues(Dictionary <HumanBodyBones, RagdollTransform> bones, RagdollProfile profile, float initialHeadOffsetFromChest)
        {
            if (bones == null)
            {
                return;
            }

            if (profile == null)
            {
                return;
            }

            // if (profile == null)
            //  profile = RagdollProfile.defaultProfile;

            Vector3 headOffset = profile.headOffset;

            //clamp head offset (values too high or too low become unstable for some reason)
            headOffset.y = Mathf.Clamp(headOffset.y, -initialHeadOffsetFromChest + .1f, 2);


            for (int i = 0; i < bonesCount; i++)
            {
                RagdollProfile.BoneProfile boneProfile = profile.boneData[humanBones[i]];

                HumanBodyBones hBodyBone = humanBones[i];

                RagdollTransform bone = bones[hBodyBone];


                //set rigidbody values for bone
                UpdateRigidbodyToProfile(bone.rigidbody, boneProfile);

                //adjust collider values for bone
                UpdateColliderToProfile(hBodyBone, bone.collider, boneProfile, headOffset, initialHeadOffsetFromChest);

                //set joint values
                if (bone.joint)
                {
                    UpdateJointToProfile(hBodyBone, bone.joint, boneProfile, headOffset);
                }
            }
        }
Пример #16
0
        public void DismemberBone(string reason, Ragdoll ragdoll, RagdollTransform bone)
        {
            InitializeDismemberedBones();
            if (!dismembermentAvailable)
            {
                return;
            }
            if (!BoneDismemberable(bone.bone.bone))
            {
                return;
            }
            if (RagdollPhysics.RigidbodyGrabbed(bone.rigidbody))
            {
                return;
            }

            // Debug.LogError("Dismembered " + reason);

            dismemberedBones[bone.bone.bone] = bone;

            // dismember the follow target, so it reflects our dismemberment
            // (dismembers the animated model...)
            if (bone.followTarget != null)
            {
                DismemberBone(ragdoll, bone.followTarget, true);
            }

            // dismember and disable any child bones (helps physics from getting all jittery)
            HumanBodyBones   childBone          = Ragdoll.GetChildBone(bone.bone.bone);
            RagdollTransform childBoneTransform = ragdoll.GetBone(childBone);

            if (!BoneDismembered(childBoneTransform))
            {
                DismemberBone(reason, ragdoll, childBoneTransform);
            }


            ragdoll.StartCoroutine(DismemberBoneDelayed(ragdoll, bone));
        }
Пример #17
0
        static void BuildJoints(Dictionary <HumanBodyBones, RagdollTransform> bones)
        {
            foreach (var k in bones.Keys)
            {
                if (k == HumanBodyBones.Hips)
                {
                    continue;
                }

                RagdollTransform bone = bones[k];

                bone.joint = bone.AddComponent <ConfigurableJoint>();

                // Setup connection and axis

                //bone.joint.autoConfigureConnectedAnchor = false;

                // turn off to handle degenerated scenarios, like spawning inside geometry.
                bone.joint.enablePreprocessing = false;

                bone.joint.anchor        = Vector3.zero;
                bone.joint.connectedBody = bones[Ragdoll.GetParentBone(k)].rigidbody;

                // Setup limits
                SoftJointLimit limit = new SoftJointLimit();
                limit.contactDistance = 0; // default to zero, which automatically sets contact distance.
                limit.limit           = 0;

                bone.joint.lowAngularXLimit = bone.joint.highAngularXLimit = bone.joint.angularYLimit = bone.joint.angularZLimit = limit;

                bone.joint.xMotion        = bone.joint.yMotion = bone.joint.zMotion = ConfigurableJointMotion.Locked;
                bone.joint.angularXMotion = bone.joint.angularYMotion = bone.joint.angularZMotion = ConfigurableJointMotion.Limited;

                bone.joint.rotationDriveMode = RotationDriveMode.Slerp;

                bone.joint.projectionMode = JointProjectionMode.PositionAndRotation;
            }
        }
Пример #18
0
 public bool BoneDismembered(RagdollTransform bone)
 {
     return(BoneDismembered(bone.bone.bone));
 }
Пример #19
0
        /*
         *      set the velocities we calculated in late update for each animated bone
         *      on the actual ragdoll
         */
        void SetPhysicsVelocities(float deltaTime)
        {
            float dot = Vector3.Dot(ragdoll.RootBone().transform.up, Vector3.up);

            float maxVelocityForGravityAdd2 = profile.maxGravityAddVelocity * profile.maxGravityAddVelocity;

            float fallDecayCurveSample = 1f - fallDecay;             //set up curves backwards... whoops

            // for each physics bone...
            for (int i = 0; i < Ragdoll.bonesCount; i++)
            {
                HumanBodyBones unityBone = Ragdoll.humanBones[i];

                RagdollTransform bone = ragdoll.GetBone(unityBone);

                if (ragdoll.BoneDismembered(bone))
                {
                    continue;
                }

                if (bone.rigidbody.isKinematic)
                {
                    continue;
                }


                Vector3 ragdollBoneVelocty = bone.rigidbody.velocity;

                // get the manually set bone decay value
                float boneDecay = boneDecays[unityBone];

                /*
                 *      calculate the force decay based on the overall fall decay and the bone profile's
                 *      fall force decay curve
                 */
                float forceDecay = Mathf.Clamp01(profile.boneData[unityBone].fallForceDecay.Evaluate(fallDecayCurveSample));

                //subtract manual decay
                forceDecay = Mathf.Clamp01(forceDecay - boneDecay);

                // if we're flipped to extremely, stop trying to follow anim
                // makes it look like it's 'gliding' forward in superman stance
                if (dot < profile.loseFollowDot)
                {
                    forceDecay = 0;
                }

                // if we're still using some force to follow
                if (forceDecay != 0)
                {
                    Vector3 animVelocity = animationVelocityTrackers[i].velocity;

                    /*
                     *      if animation velocity is below threshold magnitude, add some gravity to it
                     */
                    if (animVelocity.sqrMagnitude < maxVelocityForGravityAdd2)
                    {
                        animVelocity.y = Physics.gravity.y * deltaTime;
                    }

                    /*
                     *      if bone decay was manually set to make room for external velocities,
                     *      use the most extreme component of each vector as the "target animated" velocity
                     */
                    if (boneDecay != 0)
                    {
                        animVelocity = MaxAbs(ragdollBoneVelocty, animVelocity);
                    }

                    // set the velocity on the ragdoll rigidbody (based on the force decay)
                    bone.rigidbody.velocity = Vector3.Lerp(ragdollBoneVelocty, animVelocity, forceDecay);
                }

                if (i != 0)
                {
                    /*
                     *      calculate the force decay based on the overall fall decay and the bone profile's
                     *      fall force decay curve
                     */
                    float torqueDecay = Mathf.Clamp01(profile.boneData[unityBone].fallTorqueDecay.Evaluate(fallDecayCurveSample));

                    //subtract manual decay
                    torqueDecay = Mathf.Clamp01(torqueDecay - boneDecay);

                    /*
                     *      handle joints target for the ragdoll joints
                     */
                    HandleJointFollow(bone, profile.maxTorque * torqueDecay, i);
                }
            }

            CheckForFallEnd(fallDecay);
        }
Пример #20
0
        /*
         *  call to get the ragdoll bone references
         *
         *  animator component must be humanoid
         */
        public static bool BuildRagdollElements(Animator animator, out RagdollTransform[] allElements, out Dictionary <HumanBodyBones, RagdollTransform> boneElements)
        {
            allElements  = null;
            boneElements = null;

            //check for null animator
            if (animator == null)
            {
                Debug.LogError("No animator found...(BuildRagdollFromPrebuilt");
                return(false);// null;
            }

            List <RagdollTransform> allBonesList = new List <RagdollTransform>();

            // instance ids of the bone transforms so we dont re-add them when checking all children bones below
            HashSet <int> usedPhysicsTransforms = new HashSet <int>();

            //build bones list that use physics
            boneElements = new Dictionary <HumanBodyBones, RagdollTransform>();

            for (int i = 0; i < Ragdoll.bonesCount; i++)
            {
                HumanBodyBones humanBodyBone = Ragdoll.humanBones[i];

                Transform boneT = animator.GetBoneTransform(humanBodyBone);

                if (boneT == null)
                {
                    Debug.LogError("Cant find physics bone: " + humanBodyBone + " on ragdoll: " + animator.name);
                    boneElements          = null;
                    usedPhysicsTransforms = null;
                    return(false);
                }

                usedPhysicsTransforms.Add(boneT.GetInstanceID());

                RagdollTransform ragdollBone = new RagdollTransform(boneT, false, true, i == 0);

                boneElements.Add(humanBodyBone, ragdollBone);
                allBonesList.Add(ragdollBone);
            }

            //build other non physics bones

            //get all transform children of the hip bone
            Transform[] allChildren = allBonesList[0].transform.GetComponentsInChildren <Transform>();

            for (int i = 0; i < allChildren.Length; i++)
            {
                Transform child = allChildren[i];
                //if its not a physics bone
                if (!usedPhysicsTransforms.Contains(child.GetInstanceID()))
                {
                    bool isPhysicsParent = child.GetComponentInChildren <Rigidbody>() != null;
                    allBonesList.Add(new RagdollTransform(child, isPhysicsParent, false, false));
                }
            }
            allElements = allBonesList.ToArray();

            return(true);
        }
Пример #21
0
 public void DismemberBone(string reason, RagdollTransform bone)
 {
     dismemberment.DismemberBone(reason, this, bone);
 }
Пример #22
0
 public bool BoneDismembered(RagdollTransform bone)
 {
     return(dismemberment.BoneDismembered(bone));
 }
Пример #23
0
 public void DismemberBone(RagdollTransform bone, int delay)
 {
     dismemberment.DismemberBone(this, bone, delay, false);
 }
 public void SetFollowTarget(RagdollTransform followTarget)
 {
     this.followTarget = followTarget;
 }