using UnityEngine;
using System.Collections;
namespace RootMotion.Dynamics
{
///
/// Automatically generates a ragdoll for a Biped character.
///
[HelpURL("https://www.youtube.com/watch?v=y-luLRVmL7E&index=1&list=PLVxSIA1OaTOuE2SB9NUbckQ9r2hTg4mvL")]
[AddComponentMenu("Scripts/RootMotion.Dynamics/Ragdoll Manager/Biped Ragdoll Creator")]
public class BipedRagdollCreator : RagdollCreator
{
// Open the User Manual URL
[ContextMenu("User Manual")]
void OpenUserManual()
{
Application.OpenURL("http://root-motion.com/puppetmasterdox/html/page1.html");
}
// Open the Script Reference URL
[ContextMenu("Scrpt Reference")]
void OpenScriptReference()
{
Application.OpenURL("http://root-motion.com/puppetmasterdox/html/class_root_motion_1_1_dynamics_1_1_biped_ragdoll_creator.html#details");
}
// Open a video tutorial about setting up the component
[ContextMenu("TUTORIAL VIDEO")]
void OpenTutorial()
{
Application.OpenURL("https://www.youtube.com/watch?v=y-luLRVmL7E&index=1&list=PLVxSIA1OaTOuE2SB9NUbckQ9r2hTg4mvL");
}
public bool canBuild;
public BipedRagdollReferences references;
public Options options = Options.Default;
[System.Serializable]
public struct Options
{
//[SpaceAttribute(10)]
public float weight;
[HeaderAttribute("Optional Bones")]
public bool spine;
public bool chest;
public bool hands;
public bool feet;
[HeaderAttribute("Joints")]
public JointType joints;
public float jointRange;
[HeaderAttribute("Colliders")]
public float colliderLengthOverlap;
public ColliderType torsoColliders;
public ColliderType headCollider;
public ColliderType armColliders;
public ColliderType handColliders;
public ColliderType legColliders;
public ColliderType footColliders;
public bool fixFootColliderRotation;
public static Options Default
{
get
{
Options o = new Options();
// General Settings
o.weight = 75f;
o.colliderLengthOverlap = 0.1f;
o.jointRange = 1f;
o.chest = true;
o.headCollider = ColliderType.Capsule;
o.armColliders = ColliderType.Capsule;
o.hands = true;
o.handColliders = ColliderType.Capsule;
o.legColliders = ColliderType.Capsule;
o.feet = true;
o.fixFootColliderRotation = true;
return o;
}
}
}
public static Options AutodetectOptions(BipedRagdollReferences r)
{
Options o = Options.Default;
if (r.spine == null) o.spine = false;
if (r.chest == null) o.chest = false;
// If chest bone is too high
if (o.chest && Vector3.Dot(r.root.up, r.chest.position - GetUpperArmCentroid(r)) > 0f)
{
o.chest = false;
if (r.spine != null) o.spine = true;
}
return o;
}
public static void Create(BipedRagdollReferences r, Options options)
{
string msg = string.Empty;
if (!r.IsValid(ref msg))
{
Debug.LogWarning(msg);
return;
}
// Clean up
ClearAll(r.root);
// Colliders
CreateColliders(r, options);
// Rigidbodies
MassDistribution(r, options);
// Joints
CreateJoints(r, options);
}
private static void CreateColliders(BipedRagdollReferences r, Options options)
{
// Torso
Vector3 upperArmToHeadCentroid = GetUpperArmToHeadCentroid(r);
if (r.spine == null) options.spine = false;
if (r.chest == null) options.chest = false;
Vector3 shoulderDirection = r.rightUpperArm.position - r.leftUpperArm.position;
float torsoWidth = shoulderDirection.magnitude;
float torsoProportionAspect = 0.6f;
// Hips
Vector3 hipsStartPoint = r.hips.position;
// Making sure the hip bone is not at the feet
float toHead = Vector3.Distance(r.head.position, r.root.position);
float toHips = Vector3.Distance(r.hips.position, r.root.position);
if (toHips < toHead * 0.2f)
{
hipsStartPoint = Vector3.Lerp(r.leftUpperLeg.position, r.rightUpperLeg.position, 0.5f);
}
Vector3 lastEndPoint = options.spine ? r.spine.position : (options.chest ? r.chest.position : upperArmToHeadCentroid);
hipsStartPoint += (hipsStartPoint - upperArmToHeadCentroid) * 0.1f;
float hipsWidth = options.spine || options.chest ? torsoWidth * 0.8f : torsoWidth;
CreateCollider(r.hips, hipsStartPoint, lastEndPoint, options.torsoColliders, options.colliderLengthOverlap, hipsWidth, torsoProportionAspect, shoulderDirection);
// Spine
if (options.spine)
{
Vector3 spineStartPoint = lastEndPoint;
lastEndPoint = options.chest ? r.chest.position : upperArmToHeadCentroid;
float spineWidth = options.chest ? torsoWidth * 0.75f : torsoWidth;
CreateCollider(r.spine, spineStartPoint, lastEndPoint, options.torsoColliders, options.colliderLengthOverlap, spineWidth, torsoProportionAspect, shoulderDirection);
}
if (options.chest)
{
Vector3 chestStartPoint = lastEndPoint;
lastEndPoint = upperArmToHeadCentroid;
CreateCollider(r.chest, chestStartPoint, lastEndPoint, options.torsoColliders, options.colliderLengthOverlap, torsoWidth, torsoProportionAspect, shoulderDirection);
}
// Head
Vector3 headStartPoint = lastEndPoint;
Vector3 headEndPoint = headStartPoint + (headStartPoint - hipsStartPoint) * 0.45f;
Vector3 axis = r.head.TransformVector(AxisTools.GetAxisVectorToDirection(r.head, headEndPoint - headStartPoint));
headEndPoint = headStartPoint + Vector3.Project(headEndPoint - headStartPoint, axis).normalized * (headEndPoint - headStartPoint).magnitude;
CreateCollider(r.head, headStartPoint, headEndPoint, options.headCollider, options.colliderLengthOverlap, Vector3.Distance(headStartPoint, headEndPoint) * 0.8f);
// Arms
float armWidthAspect = 0.4f;
float leftArmWidth = Vector3.Distance(r.leftUpperArm.position, r.leftLowerArm.position) * armWidthAspect;
CreateCollider(r.leftUpperArm, r.leftUpperArm.position, r.leftLowerArm.position, options.armColliders, options.colliderLengthOverlap, leftArmWidth);
CreateCollider(r.leftLowerArm, r.leftLowerArm.position, r.leftHand.position, options.armColliders, options.colliderLengthOverlap, leftArmWidth * 0.9f);
float rightArmWidth = Vector3.Distance(r.rightUpperArm.position, r.rightLowerArm.position) * armWidthAspect;
CreateCollider(r.rightUpperArm, r.rightUpperArm.position, r.rightLowerArm.position, options.armColliders, options.colliderLengthOverlap, rightArmWidth);
CreateCollider(r.rightLowerArm, r.rightLowerArm.position, r.rightHand.position, options.armColliders, options.colliderLengthOverlap, rightArmWidth * 0.9f);
// Legs
float legWidthAspect = 0.3f;
float leftLegWidth = Vector3.Distance(r.leftUpperLeg.position, r.leftLowerLeg.position) * legWidthAspect;
CreateCollider(r.leftUpperLeg, r.leftUpperLeg.position, r.leftLowerLeg.position, options.legColliders, options.colliderLengthOverlap, leftLegWidth);
CreateCollider(r.leftLowerLeg, r.leftLowerLeg.position, r.leftFoot.position, options.legColliders, options.colliderLengthOverlap, leftLegWidth * 0.9f);
float rightLegWidth = Vector3.Distance(r.rightUpperLeg.position, r.rightLowerLeg.position) * legWidthAspect;
CreateCollider(r.rightUpperLeg, r.rightUpperLeg.position, r.rightLowerLeg.position, options.legColliders, options.colliderLengthOverlap, rightLegWidth);
CreateCollider(r.rightLowerLeg, r.rightLowerLeg.position, r.rightFoot.position, options.legColliders, options.colliderLengthOverlap, rightLegWidth * 0.9f);
// Hands
if (options.hands)
{
CreateHandCollider(r.leftHand, r.leftLowerArm, r.root, options);
CreateHandCollider(r.rightHand, r.rightLowerArm, r.root, options);
}
// Feet
if (options.feet)
{
CreateFootCollider(r.leftFoot, r.leftLowerLeg, r.leftUpperLeg, r.root, options);
CreateFootCollider(r.rightFoot, r.rightLowerLeg, r.rightUpperLeg, r.root, options);
}
}
private static Collider CopyCollider(Collider c, GameObject destination)
{
if (c is CapsuleCollider)
{
var newCapsule = CopyCapsuleCollider(c as CapsuleCollider, destination);
return newCapsule as Collider;
}
else if (c is SphereCollider)
{
var newSphere = CopySphereCollider(c as SphereCollider, destination);
return newSphere as Collider;
}
else if (c is BoxCollider)
{
var newBox = CopyBoxCollider(c as BoxCollider, destination);
return newBox as Collider;
}
return null;
}
private static CapsuleCollider CopyCapsuleCollider(CapsuleCollider o, GameObject destination)
{
CapsuleCollider d = destination.GetComponent();
if (d == null) d = destination.AddComponent();
d.isTrigger = o.isTrigger;
d.sharedMaterial = o.sharedMaterial;
d.center = o.center;
d.radius = o.radius;
d.height = o.height;
d.direction = o.direction;
return d;
}
private static SphereCollider CopySphereCollider(SphereCollider o, GameObject destination)
{
SphereCollider d = destination.GetComponent();
if (d == null) d = destination.AddComponent();
d.isTrigger = o.isTrigger;
d.sharedMaterial = o.sharedMaterial;
d.center = o.center;
d.radius = o.radius;
return d;
}
private static BoxCollider CopyBoxCollider(BoxCollider o, GameObject destination)
{
BoxCollider d = destination.GetComponent();
if (d == null) d = destination.AddComponent();
d.isTrigger = o.isTrigger;
d.sharedMaterial = o.sharedMaterial;
d.center = o.center;
d.size = o.size;
return d;
}
private static void CreateHandCollider(Transform hand, Transform lowerArm, Transform root, Options options)
{
Vector3 axis = hand.TransformVector(AxisTools.GetAxisVectorToPoint(hand, GetChildCentroid(hand, lowerArm.position)));
Vector3 endPoint = hand.position - (lowerArm.position - hand.position) * 0.75f;
endPoint = hand.position + Vector3.Project(endPoint - hand.position, axis).normalized * (endPoint - hand.position).magnitude;
CreateCollider(hand, hand.position, endPoint, options.handColliders, options.colliderLengthOverlap, Vector3.Distance(endPoint, hand.position) * 0.5f);
}
private static void CreateFootCollider(Transform foot, Transform lowerLeg, Transform upperLeg, Transform root, Options options)
{
float legHeight = (upperLeg.position - foot.position).magnitude;
Vector3 axis = foot.TransformVector(AxisTools.GetAxisVectorToPoint(foot, GetChildCentroid(foot, foot.position + root.forward) + root.forward * legHeight * 0.2f));
Vector3 endPoint = foot.position + root.forward * legHeight * 0.25f;
endPoint = foot.position + Vector3.Project(endPoint - foot.position, axis).normalized * (endPoint - foot.position).magnitude;
float width = Vector3.Distance(endPoint, foot.position) * 0.5f;
Vector3 startPoint = foot.position;
bool footBelowRoot = Vector3.Dot(root.up, foot.position - root.position) < 0f;
Vector3 heightOffset = footBelowRoot ? Vector3.zero : Vector3.Project((startPoint - root.up * width * 0.5f) - root.position, root.up);
Vector3 direction = endPoint - startPoint;
startPoint -= direction * 0.2f;
if (options.fixFootColliderRotation)
{
Vector3 fAxis = AxisTools.GetAxisVectorToDirection(foot, root.forward);
if (Vector3.Dot(foot.rotation * fAxis, root.forward) < 0f) fAxis = -fAxis;
Vector3 normal = Vector3.up;
Vector3 tangent = foot.rotation * fAxis;
Vector3.OrthoNormalize(ref normal, ref tangent);
Vector3 fallback = foot.position + tangent;
Vector3 childCentroid = GetChildCentroidRecursive(foot, fallback);
Vector3 toChildC = childCentroid - foot.position;
var child = new GameObject("Foot Collider").transform;
child.parent = foot;
child.localPosition = Vector3.zero;
child.localRotation = Quaternion.identity;
var collider = CreateCollider(child, startPoint - heightOffset, endPoint - heightOffset, options.footColliders, options.colliderLengthOverlap, width, foot);
child.rotation = Quaternion.FromToRotation(child.rotation * fAxis, childCentroid - child.position) * child.rotation;
Orthogonize(child, root.forward, root.up);
Orthogonize(child, root.right, root.up);
if (childCentroid != fallback)
{
Vector3 center = Vector3.Lerp(foot.position, childCentroid, 0.5f);
Vector3 colliderCenter = GetColliderCenter(collider);
child.position += center - colliderCenter;
float bottomY = GetColliderBottom(collider, root.up);
child.position += Vector3.up * (root.position.y - bottomY);
}
}
else
{
CreateCollider(foot, startPoint - heightOffset, endPoint - heightOffset, options.footColliders, options.colliderLengthOverlap, width);
}
}
public static Collider FixFootCollider(Transform foot, Transform root)
{
Vector3 fAxis = AxisTools.GetAxisVectorToDirection(foot, root.forward);
if (Vector3.Dot(foot.rotation * fAxis, root.forward) < 0f) fAxis = -fAxis;
Vector3 normal = Vector3.up;
Vector3 tangent = foot.rotation * fAxis;
Vector3.OrthoNormalize(ref normal, ref tangent);
Vector3 fallback = foot.position + tangent;
Vector3 childCentroid = GetChildCentroidRecursive(foot, fallback);
Vector3 toChildC = childCentroid - foot.position;
var child = new GameObject("Foot Collider").transform;
child.parent = foot;
child.localPosition = Vector3.zero;
child.localRotation = Quaternion.identity;
var footCollider = foot.GetComponent();
var collider = CopyCollider(footCollider, child.gameObject);
if (Application.isPlaying)
{
Destroy(footCollider);
}
else
{
DestroyImmediate(footCollider);
}
child.rotation = Quaternion.FromToRotation(child.rotation * fAxis, childCentroid - child.position) * child.rotation;
Orthogonize(child, root.forward, root.up);
Orthogonize(child, root.right, root.up);
if (childCentroid != fallback)
{
Vector3 center = Vector3.Lerp(foot.position, childCentroid, 0.5f);
Vector3 colliderCenter = GetColliderCenter(collider);
child.position += center - colliderCenter;
float bottomY = GetColliderBottom(collider, root.up);
child.position += Vector3.up * (root.position.y - bottomY);
}
return collider;
}
private static Vector3 GetColliderCenter(Collider c)
{
if (c is BoxCollider)
{
return c.transform.TransformPoint((c as BoxCollider).center);
}
if (c is CapsuleCollider)
{
return c.transform.TransformPoint((c as CapsuleCollider).center);
}
return c.transform.position;
}
private static float GetColliderBottom(Collider c, Vector3 up)
{
var t = c.transform;
if (c is BoxCollider)
{
var box = c as BoxCollider;
Vector3 axis = AxisTools.GetAxisVectorToDirection(t, -up);
if (Vector3.Dot(t.rotation * axis, -up) < 0f) axis = -axis;
var scaled = Vector3.Scale(box.size, axis * 0.5f);
return (t.TransformPoint(box.center) + t.rotation * scaled).y;
}
if (c is CapsuleCollider)
{
var capsule = c as CapsuleCollider;
Vector3 axis = AxisTools.GetAxisVectorToDirection(t, -up);
if (Vector3.Dot(t.rotation * axis, -up) < 0f) axis = -axis;
var scaled = capsule.radius * axis * 0.5f;
return (t.TransformPoint(capsule.center) + t.rotation * scaled).y;
}
return GetColliderCenter(c).y;
}
private static void Orthogonize(Transform t, Vector3 direction, Vector3 normal)
{
Vector3 axis = AxisTools.GetAxisVectorToDirection(t, direction);
if (Vector3.Dot(t.rotation * axis, direction) < 0f) axis = -axis;
Vector3 tangent = t.rotation * axis;
Vector3.OrthoNormalize(ref normal, ref tangent);
t.rotation = Quaternion.FromToRotation(t.rotation * axis, tangent) * t.rotation;
}
private static Vector3 GetChildCentroidRecursive(Transform t, Vector3 fallback)
{
var children = t.GetComponentsInChildren();
if (children.Length < 2) return fallback;
Vector3 c = Vector3.zero;
for (int i = 1; i < children.Length; i++)
{
c += children[i].position;
}
c /= children.Length - 1;
return c;
}
private static Vector3 GetChildCentroid(Transform t, Vector3 fallback)
{
if (t.childCount == 0) return fallback;
Vector3 c = Vector3.zero;
for (int i = 0; i < t.childCount; i++)
{
c += t.GetChild(i).position;
}
c /= (float)t.childCount;
return c;
}
private static void MassDistribution(BipedRagdollReferences r, Options o)
{
int torsoBones = 3;
if (r.spine == null)
{
o.spine = false;
torsoBones--;
}
if (r.chest == null)
{
o.chest = false;
torsoBones--;
}
float torsoPrc = 0.508f / (float)torsoBones;
float headPrc = 0.0732f;
float upperArmPrc = 0.027f;
float lowerArmPrc = 0.016f;
float handPrc = 0.0066f;
float upperLegPrc = 0.0988f;
float lowerLegPrc = 0.0465f;
float footPrc = 0.0145f;
r.hips.GetComponent().mass = torsoPrc * o.weight;
if (o.spine) r.spine.GetComponent().mass = torsoPrc * o.weight;
if (o.chest) r.chest.GetComponent().mass = torsoPrc * o.weight;
r.head.GetComponent().mass = headPrc * o.weight;
r.leftUpperArm.GetComponent().mass = upperArmPrc * o.weight;
r.rightUpperArm.GetComponent().mass = r.leftUpperArm.GetComponent().mass;
r.leftLowerArm.GetComponent().mass = lowerArmPrc * o.weight;
r.rightLowerArm.GetComponent().mass = r.leftLowerArm.GetComponent().mass;
if (o.hands)
{
r.leftHand.GetComponent().mass = handPrc * o.weight;
r.rightHand.GetComponent().mass = r.leftHand.GetComponent().mass;
}
r.leftUpperLeg.GetComponent().mass = upperLegPrc * o.weight;
r.rightUpperLeg.GetComponent().mass = r.leftUpperLeg.GetComponent().mass;
r.leftLowerLeg.GetComponent().mass = lowerLegPrc * o.weight;
r.rightLowerLeg.GetComponent().mass = r.leftLowerLeg.GetComponent().mass;
if (o.feet)
{
r.leftFoot.GetComponent().mass = footPrc * o.weight;
r.rightFoot.GetComponent().mass = r.leftFoot.GetComponent().mass;
}
}
private static void CreateJoints(BipedRagdollReferences r, Options o)
{
// Torso
if (r.spine == null) o.spine = false;
if (r.chest == null) o.chest = false;
float spineMinSwing = -30f * o.jointRange;
float spineMaxSwing = 10f * o.jointRange;
float spineSwing2 = 25f * o.jointRange;
float spineTwist = 25f * o.jointRange;
CreateJoint(new CreateJointParams(
r.hips.GetComponent(),
null,
(o.spine ? r.spine : (o.chest ? r.chest : r.head)),
r.root.right,
new CreateJointParams.Limits(0f, 0f, 0f, 0f),
o.joints
));
if (o.spine)
{
CreateJoint(new CreateJointParams(
r.spine.GetComponent(),
r.hips.GetComponent(),
(o.chest ? r.chest : r.head),
r.root.right,
new CreateJointParams.Limits(spineMinSwing, spineMaxSwing, spineSwing2, spineTwist),
o.joints
));
}
if (o.chest)
{
CreateJoint(new CreateJointParams(
r.chest.GetComponent(),
(o.spine ? r.spine.GetComponent() : r.hips.GetComponent()),
r.head,
r.root.right,
new CreateJointParams.Limits(spineMinSwing, spineMaxSwing, spineSwing2, spineTwist),
o.joints
));
}
// Head
Transform lastTorsoBone = o.chest ? r.chest : (o.spine ? r.spine : r.hips);
CreateJoint(new CreateJointParams(
r.head.GetComponent(),
lastTorsoBone.GetComponent(),
null,
r.root.right,
new CreateJointParams.Limits(-30f, 30f, 30f, 85f),
o.joints
));
// Arms
CreateJointParams.Limits upperArmLimits = new CreateJointParams.Limits(-35f * o.jointRange, 120f * o.jointRange, 85f * o.jointRange, 45 * o.jointRange);
CreateJointParams.Limits lowerArmLimits = new CreateJointParams.Limits(0f, 140f * o.jointRange, 10f * o.jointRange, 45f * o.jointRange);
CreateJointParams.Limits handLimits = new CreateJointParams.Limits(-50f * o.jointRange, 50f * o.jointRange, 50f * o.jointRange, 25f * o.jointRange);
// Left Arm
CreateLimbJoints(
lastTorsoBone,
r.leftUpperArm,
r.leftLowerArm,
r.leftHand,
r.root,
-r.root.right,
o.joints,
upperArmLimits,
lowerArmLimits,
handLimits);
// Right Arm
CreateLimbJoints(
lastTorsoBone,
r.rightUpperArm,
r.rightLowerArm,
r.rightHand,
r.root,
r.root.right,
o.joints,
upperArmLimits,
lowerArmLimits,
handLimits);
// Legs
CreateJointParams.Limits upperLegLimits = new CreateJointParams.Limits(-120f * o.jointRange, 35f * o.jointRange, 85f * o.jointRange, 45 * o.jointRange);
CreateJointParams.Limits lowerLegLimits = new CreateJointParams.Limits(0f, 140f * o.jointRange, 10f * o.jointRange, 45f * o.jointRange);
CreateJointParams.Limits footLimits = new CreateJointParams.Limits(-50f * o.jointRange, 50f * o.jointRange, 50f * o.jointRange, 25f * o.jointRange);
// Left Leg
CreateLimbJoints(
r.hips,
r.leftUpperLeg,
r.leftLowerLeg,
r.leftFoot,
r.root,
-r.root.up,
o.joints,
upperLegLimits,
lowerLegLimits,
footLimits);
// Right Leg
CreateLimbJoints(
r.hips,
r.rightUpperLeg,
r.rightLowerLeg,
r.rightFoot,
r.root,
-r.root.up,
o.joints,
upperLegLimits,
lowerLegLimits,
footLimits);
}
private static void CreateLimbJoints(Transform connectedBone, Transform bone1, Transform bone2, Transform bone3, Transform root, Vector3 defaultWorldDirection, JointType jointType, CreateJointParams.Limits limits1, CreateJointParams.Limits limits2, CreateJointParams.Limits limits3)
{
Quaternion bone1DefaultLocalRotation = bone1.localRotation;
bone1.rotation = Quaternion.FromToRotation(bone1.rotation * (bone2.position - bone1.position), defaultWorldDirection) * bone1.rotation;
Vector3 bone1Dir = (bone2.position - bone1.position).normalized;
Vector3 bone2Dir = (bone3.position - bone2.position).normalized;
Vector3 bendPlaneNormal = -Vector3.Cross(bone1Dir, bone2Dir);
float bone2PoseAngleOffset = Vector3.Angle(bone1Dir, bone2Dir);
bool isVertical = Mathf.Abs(Vector3.Dot(bone1Dir, root.up)) > 0.5f;
float verticalAngleOffsetMlp = isVertical ? 100f : 1f; // Fixing Mixamo's inverted legs
// Fixing straight limbs
if (bone2PoseAngleOffset < 0.01f * verticalAngleOffsetMlp)
{
if (isVertical) bendPlaneNormal = Vector3.Dot(bone1Dir, root.up) > 0f ? root.right : -root.right;
else bendPlaneNormal = Vector3.Dot(bone1Dir, root.right) > 0f ? root.up : -root.up;
//Debug.LogWarning("Limb " + bone1.name + ", " + bone2.name + ", " + bone3.name + " appears to be completely stretched out, Ragdoll Creator can not know how to assign joint limits. Please rotate the elbow/knee bone slightly towards its natural bending direction.");
}
CreateJoint(new CreateJointParams(
bone1.GetComponent(),
connectedBone.GetComponent(),
bone2,
bendPlaneNormal,
limits1,
jointType
));
CreateJoint(new CreateJointParams(
bone2.GetComponent(),
bone1.GetComponent(),
bone3,
bendPlaneNormal,
new CreateJointParams.Limits(limits2.minSwing - bone2PoseAngleOffset, limits2.maxSwing - bone2PoseAngleOffset, limits2.swing2, limits2.twist),
jointType
));
if (bone3.GetComponent() != null)
{
CreateJoint(new CreateJointParams(
bone3.GetComponent(),
bone2.GetComponent(),
null,
bendPlaneNormal,
limits3,
jointType
));
}
bone1.localRotation = bone1DefaultLocalRotation;
}
public static void ClearBipedRagdoll(BipedRagdollReferences r)
{
var transforms = r.GetRagdollTransforms();
foreach (Transform t in transforms) ClearTransform(t);
}
public static bool IsClear(BipedRagdollReferences r)
{
var transforms = r.GetRagdollTransforms();
foreach (Transform t in transforms)
{
if (t.GetComponent() != null) return false;
}
return true;
}
private static Vector3 GetUpperArmToHeadCentroid(BipedRagdollReferences r)
{
return Vector3.Lerp(GetUpperArmCentroid(r), r.head.position, 0.5f);
}
private static Vector3 GetUpperArmCentroid(BipedRagdollReferences r)
{
return Vector3.Lerp(r.leftUpperArm.position, r.rightUpperArm.position, 0.5f);
}
}
}