namespace Net.Project.B.World { using UnityEngine; using UnityEngine; public class RagdollConfigurator : MonoBehaviour { void Start() { foreach (var joint in GetComponentsInChildren()) { ConfigureJointAxis(joint); ApplyJointLimits(joint); } Destroy(this); } /// /// 自动配置 ConfigurableJoint 的 axis 和 secondaryAxis /// void ConfigureJointAxis(ConfigurableJoint joint) { Transform jointTransform = joint.transform; HumanBodyBones boneType = GetBoneType(jointTransform); if (boneType == HumanBodyBones.LastBone) return; Vector3 primaryAxis; Vector3 secondaryAxis; switch (boneType) { case HumanBodyBones.Hips: case HumanBodyBones.Spine: primaryAxis = jointTransform.right; secondaryAxis = jointTransform.up; break; case HumanBodyBones.LeftUpperArm: case HumanBodyBones.RightUpperArm: primaryAxis = jointTransform.forward; // 手臂通常绕前后旋转 secondaryAxis = jointTransform.up; break; case HumanBodyBones.LeftLowerArm: case HumanBodyBones.RightLowerArm: primaryAxis = jointTransform.forward; secondaryAxis = jointTransform.right; break; case HumanBodyBones.LeftUpperLeg: case HumanBodyBones.RightUpperLeg: primaryAxis = jointTransform.right; secondaryAxis = jointTransform.up; break; case HumanBodyBones.LeftLowerLeg: case HumanBodyBones.RightLowerLeg: primaryAxis = jointTransform.right; secondaryAxis = jointTransform.forward; break; default: primaryAxis = jointTransform.right; secondaryAxis = jointTransform.up; break; } joint.axis = primaryAxis; joint.secondaryAxis = secondaryAxis; //Debug.Log($"{boneType} -> Axis: {primaryAxis}, SecondaryAxis: {secondaryAxis}"); } /// /// 自动配置关节角度限制 /// void ApplyJointLimits(ConfigurableJoint joint) { Transform jointTransform = joint.transform; HumanBodyBones boneType = GetBoneType(jointTransform); if (boneType == HumanBodyBones.LastBone) return; int muscleIndex = HumanTrait.MuscleFromBone((int)boneType, 0); if (muscleIndex < 0) return; // 获取默认角度范围,并限制在合理范围内 float minLimit = Mathf.Clamp(HumanTrait.GetMuscleDefaultMin(muscleIndex), -60f, 60f); float maxLimit = Mathf.Clamp(HumanTrait.GetMuscleDefaultMax(muscleIndex), -60f, 60f); float limitRange = Mathf.Abs(maxLimit - minLimit) * 0.5f; // 配置关节限制 SoftJointLimit limit = new SoftJointLimit { limit = limitRange }; SoftJointLimitSpring spring = new SoftJointLimitSpring { spring = 50f, damper = 10f }; joint.lowAngularXLimit = limit; joint.highAngularXLimit = limit; joint.angularYLimit = limit; joint.angularZLimit = limit; joint.angularXLimitSpring = spring; joint.angularYZLimitSpring = spring; joint.angularXMotion = ConfigurableJointMotion.Limited; joint.angularYMotion = ConfigurableJointMotion.Limited; joint.angularZMotion = ConfigurableJointMotion.Limited; // 额外优化 joint.targetRotation = Quaternion.identity; joint.configuredInWorldSpace = false; joint.enablePreprocessing = false; // 设置刚体质量 Rigidbody rb = joint.GetComponent(); if (rb != null) { rb.mass = boneType == HumanBodyBones.Hips ? 8f : 2f; } //Debug.Log($"{boneType} 关节设置完毕: 限制角度 {limitRange}"); } /// /// 通过 Transform 获取 Humanoid 骨骼类型 /// HumanBodyBones GetBoneType(Transform jointTransform) { Animator animator = GetComponent(); if (animator == null || !animator.isHuman) return HumanBodyBones.LastBone; foreach (HumanBodyBones bone in System.Enum.GetValues(typeof(HumanBodyBones))) { if (bone == HumanBodyBones.LastBone) continue; if (animator.GetBoneTransform(bone) == jointTransform) { return bone; } } return HumanBodyBones.LastBone; } } }