/* * Create a configurable joint on this BodyPart connected to target applying resistance back to the previous pose * NOTE: If maxforce is 0, the ragdoll will crumple like a chump * */ public ConfigurableJoint ConnectTo(BodyPart target, float resistance, float maxForce) { // store the current rotation and enter initialRotation to create the joint Quaternion q = bone.localRotation; bone.localRotation = _initialRotation; // ensure there is a rigidbody AddRigidbody(); rigidbody.isKinematic = true; // create the new joint and configure it joint = gameObject.AddComponent <ConfigurableJoint>(); joint.connectedBody = target.AddRigidbody(); // NOTE: this function takes care of validation internally joint.axis = jointAxis; joint.secondaryAxis = jointSecondaryAxis; joint.xMotion = joint.yMotion = joint.zMotion = ConfigurableJointMotion.Locked; joint.angularXMotion = joint.angularYMotion = joint.angularZMotion = ConfigurableJointMotion.Limited; SoftJointLimit limit = new SoftJointLimit(); limit.limit = xMin; joint.lowAngularXLimit = limit; limit.limit = xMax; joint.highAngularXLimit = limit; limit.limit = yMax; joint.angularYLimit = limit; limit.limit = zMax; joint.angularZLimit = limit; joint.rotationDriveMode = RotationDriveMode.Slerp; JointDrive drive = new JointDrive(); drive.mode = JointDriveMode.Position; drive.positionSpring = resistance; drive.maximumForce = maxForce; joint.slerpDrive = drive; joint.targetRotation = q * Quaternion.Inverse(initialRotation); // disable world-space configuration to ensure settings are applied joint.configuredInWorldSpace = false; // return to the current orientation bone.localRotation = q; rigidbody.isKinematic = false; return(joint); }
/* * Create a configurable joint on this BodyPart connected to target applying resistance back to the previous pose * NOTE: If maxforce is 0, the ragdoll will crumple like a chump * */ public ConfigurableJoint ConnectTo(BodyPart target, float resistance, float maxForce) { // store the current rotation and enter initialRotation to create the joint Quaternion q = bone.localRotation; bone.localRotation = _initialRotation; // ensure there is a rigidbody AddRigidbody(); rigidbody.isKinematic = true; // create the new joint and configure it joint = gameObject.AddComponent<ConfigurableJoint>(); joint.connectedBody = target.AddRigidbody(); // NOTE: this function takes care of validation internally joint.axis = jointAxis; joint.secondaryAxis = jointSecondaryAxis; joint.xMotion = joint.yMotion = joint.zMotion = ConfigurableJointMotion.Locked; joint.angularXMotion = joint.angularYMotion = joint.angularZMotion = ConfigurableJointMotion.Limited; SoftJointLimit limit = new SoftJointLimit(); limit.limit = xMin; joint.lowAngularXLimit = limit; limit.limit = xMax; joint.highAngularXLimit = limit; limit.limit = yMax; joint.angularYLimit = limit; limit.limit = zMax; joint.angularZLimit = limit; joint.rotationDriveMode = RotationDriveMode.Slerp; JointDrive drive = new JointDrive(); drive.mode = JointDriveMode.Position; drive.positionSpring = resistance; drive.maximumForce = maxForce; joint.slerpDrive = drive; joint.targetRotation = q*Quaternion.Inverse(initialRotation); // disable world-space configuration to ensure settings are applied joint.configuredInWorldSpace = false; // return to the current orientation bone.localRotation = q; rigidbody.isKinematic = false; return joint; }
/* * Draw custom viewport render * */ void OnSceneGUI() { // draw the shape gizmo Handles.color = shapeColor; DrawShapeHandle(part, isSymmetrical); // draw the joint handle DrawJointHandle(part, isSymmetrical); // begin GUI or transform handles will be disabled Handles.BeginGUI(); // create the viewport controls ViewportControls.BeginArea(viewportControlsWidth, GUIAnchor.TopLeft); { ViewportCommonControls(); part.isRigidbody = ViewportControls.OnOffToggle("Is Rigidbody:", part.isRigidbody); part.isCollider = ViewportControls.OnOffToggle("Is Collider:", part.isCollider); if (isSymmetrical && part.oppositePart != null) { part.oppositePart.isRigidbody = part.isRigidbody; part.oppositePart.isCollider = part.isCollider; } ViewportShapeControls(part); // if the editor is playing, then create testing controls if (Application.isPlaying) { // padding after previous controls GUILayout.Space(ViewportControls.viewportPadding * 2f); // create a button to test the joint if it does not currently have one if (part.joint == null) { if (part.isRigidbody && GUILayout.Button("Test Joint")) { // the BodyPart needs to have a parentPart defined in order to test if (part.parentPart == null) { Debug.LogError("Cannot test part: its parentPart is null.", this); } else { if (part.bone.rigidbody == null) { part.AddRigidbody(); } else { part.bone.rigidbody.isKinematic = false; } if (part.parentPart.bone.rigidbody == null) { part.parentPart.AddRigidbody(); part.parentPart.bone.rigidbody.isKinematic = true; } if (part.bone.collider == null) { part.AddCollider(); } part.ConnectToParent(jointResistance, maxForce); } } } // otherwise create a button to remove the joint else { if (GUILayout.Button("Remove Joint")) { Destroy(part.joint); Destroy(part.rigidbody); Destroy(part.collider); part.ResetToInitialRotation(); } } // only update the joint's spring and force values if the slider values have changed if (part.isRigidbody) { float oldResist = jointResistance; float oldForce = maxForce; ViewportResistanceSlider(); ViewportMaxForceSlider(); if ((oldResist != jointResistance || oldForce != maxForce) && part.joint != null) { JointDrive drive = part.joint.slerpDrive; drive.maximumForce = maxForce; drive.positionSpring = jointResistance; part.joint.slerpDrive = drive; } } } } ViewportControls.EndArea(); // display symmetry status at the top of the viewport ViewportStatus(); // finish GUI Handles.EndGUI(); }