Advertisement
Vazili_KZ

Foot IK 1.1

Mar 10th, 2021
379
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.04 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5.  
  6. namespace AGD.Core.IK
  7. {
  8.     /// <summary>
  9.     /// To be placed on a character in order to add a foot IK grounding behaviour
  10.     /// Requires an Animator with a Layer set to IK Pass
  11.     /// </summary>
  12.     [RequireComponent(typeof(Animator))]
  13.     public class FootIK : MonoBehaviour
  14.     {
  15.        
  16.  
  17.         [Tooltip("Set to false and this script won't run.")]
  18.         [SerializeField] private bool applyFootIK = true;
  19.        
  20.         [Tooltip("Select the layer to which the foot IK will be applied")]
  21.         [SerializeField] private LayerMask targetLayer;
  22.  
  23.         [Tooltip("the distance of the ray check from the IK Foot Transform towards the ground")]
  24.         [Range(0,1)][SerializeField] private float checkDistance = 0;
  25.  
  26.         [Tooltip("the offset from the IK Foot Transform to the lowest point of the foot")]
  27.         [Range(0,1)][SerializeField] private float feetOffset = 0;
  28.  
  29.         private Animator _animator;
  30.         private Collider _collider;
  31.        
  32.        
  33.         private void Start()
  34.         {
  35.             _animator = GetComponent<Animator>();
  36.             _collider = GetComponent<Collider>();
  37.         }
  38.  
  39.         private void OnAnimatorIK(int layerIndex)
  40.         {
  41.             if (!applyFootIK) return;
  42.             if (!_animator) return;
  43.            
  44.             // Set the weights of feet IK to the current value defined by the curve in the animations.
  45.             _animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, _animator.GetFloat("IKLeftFootWeight"));
  46.             _animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, _animator.GetFloat("IKLeftFootWeight"));
  47.             _animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, _animator.GetFloat("IKRightFootWeight"));
  48.             _animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, _animator.GetFloat("IKRightFootWeight"));
  49.            
  50.             //Variables used to calculated pelvis position after calculating the feet position
  51.             var leftFootYOffset = 0f;
  52.             var rightFootYOffset = 0f;
  53.            
  54.             //Setting IK Positions
  55.            
  56.             //Left Foot
  57.             RaycastHit hitInfo_1;
  58.             RaycastHit hitInfo_2;
  59.             //a ray starting from the center of the collider and going downward on the Y Axis
  60.             Ray ray_1 = new Ray(_animator.GetIKPosition(AvatarIKGoal.LeftFoot) + new Vector3(0,_collider.bounds.extents.y,0), Vector3.down);
  61.             Ray ray_2 = new Ray(_animator.GetIKPosition(AvatarIKGoal.LeftFoot) + new Vector3(0,_collider.bounds.extents.y,.15f), Vector3.down);
  62.             Debug.DrawRay(_animator.GetIKPosition(AvatarIKGoal.LeftFoot) + new Vector3(0,_collider.bounds.extents.y,0),
  63.                 Vector3.down * (_collider.bounds.extents.y + checkDistance), Color.red);
  64.             Debug.DrawRay(_animator.GetIKPosition(AvatarIKGoal.LeftFoot) + new Vector3(0,_collider.bounds.extents.y,.15f),
  65.                 Vector3.down * (_collider.bounds.extents.y + checkDistance / 2), Color.red);
  66.            
  67.             if (Physics.Raycast(ray_1, out hitInfo_1, _collider.bounds.extents.y + checkDistance,
  68.                 targetLayer))
  69.             {
  70.                 //the length of the offset between the current foot position and it's target position
  71.                 leftFootYOffset = (hitInfo_1.point - _animator.GetIKPosition(AvatarIKGoal.LeftFoot)).magnitude;
  72.  
  73.                 var footPosition = hitInfo_1.point; //The point in space where the ray hit the targetLayer ie: where the foot should be placed.
  74.                 footPosition.y += feetOffset; //lifting the foot back up to compensate for the feet Offset.
  75.                 _animator.SetIKPosition(AvatarIKGoal.LeftFoot, footPosition);
  76.                 //Rotating the foot in a direction so that Vector3.up's rotation matches the hit surface's normal rotation.
  77.                 _animator.SetIKRotation(AvatarIKGoal.LeftFoot, Quaternion.FromToRotation(Vector3.up, hitInfo_1.normal));
  78.             }
  79.             else if (Physics.Raycast(ray_2, out hitInfo_2, _collider.bounds.extents.y + checkDistance / 2,
  80.                 targetLayer))
  81.             {
  82.                 //the length of the offset between the current foot position and it's target position
  83.                 leftFootYOffset = (hitInfo_2.point - new Vector3(0,0,.15f) - _animator.GetIKPosition(AvatarIKGoal.LeftFoot)).magnitude;
  84.                
  85.                 var footPosition = hitInfo_2.point - new Vector3(0,0,.15f); // same logic as above but with an offset that is the foot-toes distance.
  86.                 footPosition.y += feetOffset; //lifting the foot back up to compensate for the feet Offset.
  87.                 _animator.SetIKPosition(AvatarIKGoal.LeftFoot, footPosition);
  88.                 //Rotating the foot in a direction so that Vector3.up's rotation matches the hit surface's normal rotation.
  89.                 _animator.SetIKRotation(AvatarIKGoal.LeftFoot, Quaternion.FromToRotation(Vector3.up, hitInfo_2.normal));
  90.             }
  91.            
  92.             //Right Foot
  93.             //a ray starting from the center of the collider and going downward on the Y Axis
  94.             ray_1 = new Ray(_animator.GetIKPosition(AvatarIKGoal.RightFoot) + new Vector3(0,_collider.bounds.extents.y,0), Vector3.down);
  95.             ray_2 = new Ray(_animator.GetIKPosition(AvatarIKGoal.RightFoot) + new Vector3(0,_collider.bounds.extents.y,.15f), Vector3.down);
  96.             Debug.DrawRay(_animator.GetIKPosition(AvatarIKGoal.RightFoot) + new Vector3(0,_collider.bounds.extents.y,0),
  97.                 Vector3.down * (_collider.bounds.extents.y + checkDistance), Color.red);
  98.             Debug.DrawRay(_animator.GetIKPosition(AvatarIKGoal.RightFoot) + new Vector3(0,_collider.bounds.extents.y,.15f),
  99.                 Vector3.down * (_collider.bounds.extents.y + checkDistance / 2), Color.red);
  100.            
  101.             if (Physics.Raycast(ray_1, out hitInfo_1, _collider.bounds.extents.y + checkDistance,
  102.                 targetLayer))
  103.             {
  104.                 //the length of the offset between the current foot position and it's target position
  105.                 rightFootYOffset = (hitInfo_1.point - _animator.GetIKPosition(AvatarIKGoal.RightFoot)).magnitude;
  106.  
  107.                 var footPosition = hitInfo_1.point; //The point in space where the ray hit the targetLayer ie: where the foot should be placed.
  108.                 footPosition.y += feetOffset; //lifting the foot back up to compensate for the feet Offset.
  109.                 _animator.SetIKPosition(AvatarIKGoal.RightFoot, footPosition);
  110.                 //Rotating the foot in a direction so that Vector3.up's rotation matches the hit surface's normal rotation.
  111.                 _animator.SetIKRotation(AvatarIKGoal.RightFoot, Quaternion.FromToRotation(Vector3.up, hitInfo_1.normal));
  112.             }
  113.             else if (Physics.Raycast(ray_2, out hitInfo_2, _collider.bounds.extents.y + checkDistance / 2,
  114.                 targetLayer))
  115.             {
  116.                 //the length of the offset between the current foot position and it's target position
  117.                 rightFootYOffset = (hitInfo_2.point - new Vector3(0,0,.15f) - _animator.GetIKPosition(AvatarIKGoal.RightFoot)).magnitude;
  118.                
  119.                 var footPosition = hitInfo_2.point - new Vector3(0,0,.15f); // same logic as above but with an offset that is the foot-toes distance.
  120.                 footPosition.y += feetOffset; //lifting the foot back up to compensate for the feet Offset.
  121.                 _animator.SetIKPosition(AvatarIKGoal.RightFoot, footPosition);
  122.                 //Rotating the foot in a direction so that Vector3.up's rotation matches the hit surface's normal rotation.
  123.                 _animator.SetIKRotation(AvatarIKGoal.RightFoot, Quaternion.FromToRotation(Vector3.up, hitInfo_2.normal));
  124.             }
  125.            
  126.            
  127.             //Pelvis
  128.             var pelvisYOffset = Mathf.Max(leftFootYOffset, rightFootYOffset);
  129.             var pelvisOffset = new Vector3(0,pelvisYOffset,0);
  130.             _animator.bodyPosition -= pelvisOffset * _animator.GetFloat("IKPelvisWeight");
  131.         }
  132.     }
  133. }
  134.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement