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 | } |