public PlayerIK() { for (var i = 0; i <= (int)AvatarIKGoal.RightHand; ++i) { _params[i] = new IKParam(); } }
private void DisableIK(IKParam param) { if (param.Animator != null && param.Layer >= 0 && param.Source != null) { param.Weight = 0; } }
/// <summary> /// Set IK Rotation /// </summary> /// <param name="rotation"></param> private void SetIKRotation(IKParam param) { if (!(param.RootBone && param.MiddleBone && param.EndBone) || param.Weight <= 0.0f) { return; } param.EndBone.rotation = Quaternion.Slerp(param.EndBone.rotation, param.Source.rotation, param.Weight); }
private void EnableIKLayerWeight(IKParam param) { if (param.Animator != null && param.Layer >= 0 && param.Source != null) { param.Animator.SetLayerWeight(param.Layer, 1); param.Weight = 1; } }
private void EnableIK(IKParam param) { // 对于第三人称的手,相应的参数均为初始值 if (param.Animator != null && param.Layer >= 0 && param.Source != null) { SetIKPosition(param); SetIKRotation(param); } }
/// <summary> /// Set IK Position /// </summary> /// <param name="ikPosition"></param> private void SetIKPosition(IKParam param) { if (!(param.RootBone && param.MiddleBone && param.EndBone) || param.Weight <= 0.0f) { return; } // Calculate middleBone Direction Vector3 middleBoneDirection = Vector3.zero; var rootBonePosition = param.RootBone.position; var endBonePosition = param.EndBone.position; var middleBonePosition = param.MiddleBone.position; var sourcePosition = param.Source.position; var rootBoneRotation = param.RootBone.rotation; var middleBoneRotation = param.MiddleBone.rotation; if (param.HintPosition != Vector3.zero) // if middleBoneGoal is null, the direction will be calculated with forearm's point { middleBoneDirection = param.HintPosition - rootBonePosition; } else { middleBoneDirection = Vector3.Cross(endBonePosition - rootBonePosition, Vector3.Cross(endBonePosition - rootBonePosition, endBonePosition - middleBonePosition)); } // Get lengths of Arm float rootBoneLength = (middleBonePosition - rootBonePosition).magnitude; float middleBoneLength = (endBonePosition - middleBonePosition).magnitude; // Calculate the desired middleBone position Vector3 middleBonePos = GetHintPosition(rootBonePosition, sourcePosition, rootBoneLength, middleBoneLength, middleBoneDirection); // Rotate the bone transformations to align correctly Quaternion upperarmRotation = Quaternion.FromToRotation(middleBonePosition - rootBonePosition, middleBonePos - rootBonePosition) * rootBoneRotation; if (!(System.Single.IsNaN(upperarmRotation.x) || System.Single.IsNaN(upperarmRotation.y) || System.Single.IsNaN(upperarmRotation.z))) { //Rotate with transition param.RootBone.rotation = Quaternion.Slerp(rootBoneRotation, upperarmRotation, param.Weight); Quaternion r = Quaternion.FromToRotation(endBonePosition - middleBonePosition, sourcePosition - middleBonePos) * middleBoneRotation; param.MiddleBone.rotation = Quaternion.Slerp(middleBoneRotation, r, param.Weight); } param.HintPosition = Vector3.zero; }
private void FindIkBones(AvatarIKGoal goal, IKParam param) { var animator = param.Animator; if (null == animator) { _logger.ErrorFormat("IkAnimatorIsNull"); return; } switch (goal) { case AvatarIKGoal.LeftHand: param.RootBone = GetBoneTransform(animator, HumanBodyBones.LeftUpperArm); param.MiddleBone = GetBoneTransform(animator, HumanBodyBones.LeftLowerArm); param.EndBone = GetBoneTransform(animator, HumanBodyBones.LeftHand); break; case AvatarIKGoal.RightHand: param.RootBone = GetBoneTransform(animator, HumanBodyBones.RightUpperArm); param.MiddleBone = GetBoneTransform(animator, HumanBodyBones.RightLowerArm); param.EndBone = GetBoneTransform(animator, HumanBodyBones.RightHand); break; case AvatarIKGoal.LeftFoot: param.RootBone = GetBoneTransform(animator, HumanBodyBones.LeftUpperLeg); param.MiddleBone = GetBoneTransform(animator, HumanBodyBones.LeftLowerLeg); param.EndBone = GetBoneTransform(animator, HumanBodyBones.LeftFoot); break; case AvatarIKGoal.RightFoot: param.RootBone = GetBoneTransform(animator, HumanBodyBones.RightUpperLeg); param.MiddleBone = GetBoneTransform(animator, HumanBodyBones.RightLowerLeg); param.EndBone = GetBoneTransform(animator, HumanBodyBones.RightFoot); break; } }
/// <summary> /// Set IK Hint Position /// ps: Call before SetIKPosition /// </summary> /// <param name="hintPosition"></param> private void SetIKHintPosition(IKParam param, Vector3 hintPosition) { param.HintPosition = hintPosition; }