SHOW:
|
|
- or go back to the newest paste.
| 1 | using System.Collections; | |
| 2 | using System.Collections.Generic; | |
| 3 | using UnityEngine; | |
| 4 | ||
| 5 | public class CharacterIK : MonoBehaviour {
| |
| 6 | ||
| 7 | Animator anim; | |
| 8 | ||
| 9 | Transform leftFoot; | |
| 10 | Transform rightFoot; | |
| 11 | ||
| 12 | Transform rightShoulder; | |
| 13 | Transform leftShoulder; | |
| 14 | ||
| 15 | Vector3 leftFoot_pos; | |
| 16 | Vector3 rightFoot_pos; | |
| 17 | ||
| 18 | Quaternion leftFoot_rot; | |
| 19 | Quaternion rightFoot_rot; | |
| 20 | ||
| 21 | Vector3 leftHand_pos; | |
| 22 | Vector3 rightHand_pos; | |
| 23 | ||
| 24 | Quaternion leftHand_rot; | |
| 25 | Quaternion rightHand_rot; | |
| 26 | ||
| 27 | float leftFoot_Weight; | |
| 28 | float rightFoot_Weight; | |
| 29 | ||
| 30 | float leftHand_Weight; | |
| 31 | float rightHand_Weight; | |
| 32 | ||
| 33 | public Transform lookAtThis; | |
| 34 | ||
| 35 | private void Start() | |
| 36 | {
| |
| 37 | anim = GetComponent<Animator>(); | |
| 38 | leftFoot = anim.GetBoneTransform(HumanBodyBones.LeftFoot); | |
| 39 | rightFoot = anim.GetBoneTransform(HumanBodyBones.RightFoot); | |
| 40 | leftShoulder = anim.GetBoneTransform(HumanBodyBones.LeftShoulder); | |
| 41 | rightShoulder = anim.GetBoneTransform(HumanBodyBones.RightShoulder); | |
| 42 | } | |
| 43 | private void OnAnimatorIK(int layerIndex) | |
| 44 | {
| |
| 45 | // foot IK | |
| 46 | leftFoot_Weight = anim.GetFloat("LeftFoot");
| |
| 47 | rightFoot_Weight = anim.GetFloat("RightFoot");
| |
| 48 | // find raycast positions | |
| 49 | FindFloorPositions(leftFoot, ref leftFoot_pos, ref leftFoot_rot, Vector3.up); | |
| 50 | FindFloorPositions(rightFoot, ref rightFoot_pos, ref rightFoot_rot, Vector3.up); | |
| 51 | ||
| 52 | // replace the weights with leftFoot_Weight, and rightFoot_Weight when you've set them in your animation's Curves | |
| 53 | anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1); | |
| 54 | anim.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1); | |
| 55 | ||
| 56 | anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1); | |
| 57 | anim.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1); | |
| 58 | ||
| 59 | // set the position of the feet | |
| 60 | anim.SetIKPosition(AvatarIKGoal.LeftFoot, leftFoot_pos); | |
| 61 | anim.SetIKPosition(AvatarIKGoal.RightFoot, rightFoot_pos); | |
| 62 | ||
| 63 | // set the rotation of the feet | |
| 64 | anim.SetIKRotation(AvatarIKGoal.LeftFoot, leftFoot_rot); | |
| 65 | anim.SetIKRotation(AvatarIKGoal.RightFoot, rightFoot_rot); | |
| 66 | ||
| 67 | // hand IK | |
| 68 | ||
| 69 | // find raycast positions | |
| 70 | FindFloorPositions(leftShoulder, ref leftHand_pos, ref leftHand_rot, -transform.forward); | |
| 71 | FindFloorPositions(rightShoulder, ref rightHand_pos, ref rightHand_rot, -transform.forward); | |
| 72 | ||
| 73 | // distance between hands and raycast hit | |
| 74 | float distanceRightArmObject = Vector3.Distance(anim.GetBoneTransform(HumanBodyBones.RightShoulder).position, rightHand_pos); | |
| 75 | float distanceLeftArmObject = Vector3.Distance(anim.GetBoneTransform(HumanBodyBones.LeftShoulder).position, leftHand_pos); | |
| 76 | // blend weight based on the distance | |
| 77 | leftHand_Weight = Mathf.Clamp01(1 - distanceLeftArmObject); | |
| 78 | rightHand_Weight = Mathf.Clamp01(1 - distanceRightArmObject); | |
| 79 | ||
| 80 | ||
| 81 | anim.SetIKPositionWeight(AvatarIKGoal.LeftHand, leftHand_Weight); | |
| 82 | anim.SetIKRotationWeight(AvatarIKGoal.LeftHand, leftHand_Weight); | |
| 83 | ||
| 84 | anim.SetIKPositionWeight(AvatarIKGoal.RightHand, rightHand_Weight); | |
| 85 | anim.SetIKRotationWeight(AvatarIKGoal.RightHand, rightHand_Weight); | |
| 86 | ||
| 87 | // set the position of the hand | |
| 88 | anim.SetIKPosition(AvatarIKGoal.LeftHand, leftHand_pos); | |
| 89 | anim.SetIKPosition(AvatarIKGoal.RightHand, rightHand_pos); | |
| 90 | ||
| 91 | // set the rotation of the hand | |
| 92 | anim.SetIKRotation(AvatarIKGoal.LeftHand, leftHand_rot); | |
| 93 | anim.SetIKRotation(AvatarIKGoal.RightHand, rightHand_rot); | |
| 94 | // head IK | |
| 95 | if (lookAtThis != null) | |
| 96 | {
| |
| 97 | // distance between face and object to look at | |
| 98 | float distanceFaceObject = Vector3.Distance(anim.GetBoneTransform(HumanBodyBones.Head).position, lookAtThis.position); | |
| 99 | ||
| 100 | anim.SetLookAtPosition(lookAtThis.position); | |
| 101 | // blend based on the distance | |
| 102 | anim.SetLookAtWeight(Mathf.Clamp01(2 - distanceFaceObject), Mathf.Clamp01(1 - distanceFaceObject)); | |
| 103 | } | |
| 104 | } | |
| 105 | ||
| 106 | void FindFloorPositions(Transform t, ref Vector3 targetPosition, ref Quaternion targetRotation, Vector3 direction) | |
| 107 | {
| |
| 108 | RaycastHit hit; | |
| 109 | Vector3 rayOrigin = t.position; | |
| 110 | // move the ray origin back a bit | |
| 111 | rayOrigin += direction * 0.3f; | |
| 112 | ||
| 113 | // raycast in the given direction | |
| 114 | Debug.DrawRay(rayOrigin, -direction, Color.green); | |
| 115 | if (Physics.Raycast(rayOrigin, -direction, out hit, 3)) | |
| 116 | {
| |
| 117 | // the hit point is the position of the hand/foot | |
| 118 | targetPosition = hit.point; | |
| 119 | // then rotate based on the hit normal | |
| 120 | Quaternion rot = Quaternion.LookRotation(transform.forward); | |
| 121 | targetRotation = Quaternion.FromToRotation(Vector3.up, hit.normal) * rot; | |
| 122 | } | |
| 123 | } | |
| 124 | } |