/* * Set the bone decay for the bone (in the range 0...1) * 0 = follow animation normally * 1 = dont follow animation at all */ public void SetBoneDecay(HumanBodyBones bones, float decayValue, float neighborMultiplier) { if (!boneDecays.ContainsKey(bones)) { Debug.LogError(bones + " is not a physics bone, cant set bone decay"); return; } // making additive, so in case we hit a bone twice in a ragdoll session // it doesnt reset with a lower value float origDecay = boneDecays[bones]; origDecay += decayValue; if (origDecay > 1) { origDecay = 1; } boneDecays[bones] = origDecay; if (neighborMultiplier > 0) { foreach (var n in profile.bones[Ragdoll.Bone2Index(bones)].neighbors) { SetBoneDecay(n, decayValue * neighborMultiplier, 0); } } }
/* * * actually add the rigidbody, collider, joint components that make up the ragdoll (if add components) * * measure the initial head offset from chest */ public static void BuildBones(Animator animator, RagdollProfile profile, bool addComponents, Dictionary <HumanBodyBones, RagdollTransform> boneElements, out float initialHeadOffsetFromChest) { if (addComponents) { EraseRagdoll(animator); //add capsules BuildCapsules(boneElements); AddBreastColliders(boneElements); AddHeadCollider(boneElements); //add rigidbodies BuildRigidodies(boneElements); //add joints BuildJoints(boneElements); //add bone components BuildBones(boneElements); } //initial head position from chest (used for resizing chest collider based on head offset) initialHeadOffsetFromChest = boneElements[HumanBodyBones.Chest].transform.InverseTransformPoint(boneElements[HumanBodyBones.Head].transform.position).y; // update the ragdoll to reflect it's profile values Ragdoll.UpdateBonesToProfileValues(boneElements, profile, initialHeadOffsetFromChest); }
/* * has to be public i guess... :/ */ public void _InitializeInternal(HumanBodyBones bone, Ragdoll ragdoll, Action <RagdollBone, Collision> onCollisionEnter, Action <RagdollBone, Collision> onCollisionStay, Action <RagdollBone, Collision> onCollisionExit) { this.bone = bone; this.ragdoll = ragdoll; this.onCollisionEnter += onCollisionEnter; this.onCollisionStay += onCollisionStay; this.onCollisionExit += onCollisionExit; }
/* * 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); }
/* * 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); }
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; }
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 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; }
void Start() { if (testRagdoll != null) { if (Ragdoll.BoneIsPhysicsBone(boneToHang)) { RigidbodyHangPoint hangPoint = gameObject.AddComponent <RigidbodyHangPoint>(); hangPoint.calculateOffset = calculateOffset; hangPoint.freeRotation = freeRotation; hangPoint.anchorOffset = anchorOffset; hangPoint.rigidbodyToHang = testRagdoll.GetBone(boneToHang).rigidbody; } else { Debug.LogError(boneToHang + " Is not a ragdoll physics bone"); } } }
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)); }
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; } }
void OnEnable() { ragdoll = target as Ragdoll; CheckForProfileChange(); }
public DATATYPE this[HumanBodyBones bone] { get { return(boneDatas[Ragdoll.Bone2Index(bone)].boneData); } }
void OnEnable() { ragdoll = target as Ragdoll; }