Advertisement
annapuppet

CharacterIK.cs

Jul 10th, 2022
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement