yurtle

Fixed Hand Collision Script

Jul 16th, 2020
566
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.14 KB | None | 0 0
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: handles the physics of hands colliding with the world
  4. //
  5. //=============================================================================
  6.  
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using UnityEngine;
  10.  
  11. namespace Valve.VR.InteractionSystem
  12. {
  13.     public class HandPhysics : MonoBehaviour
  14.     {
  15.         [Tooltip("Hand collider prefab to instantiate")]
  16.         public HandCollider handColliderPrefab;
  17.         [HideInInspector]
  18.         public HandCollider handCollider;
  19.  
  20.         [Tooltip("Layers to consider when checking if an area is clear")]
  21.         public LayerMask clearanceCheckMask;
  22.  
  23.         [HideInInspector]
  24.         public Hand hand;
  25.  
  26.         // distance at which hand will teleport back to controller
  27.         const float handResetDistance = 0.6f;
  28.  
  29.         const float collisionReenableClearanceRadius = 0.1f;
  30.  
  31.         private bool initialized = false;
  32.  
  33.         private bool collisionsEnabled = true;
  34.  
  35.  
  36.         private void Start()
  37.         {
  38.             hand = GetComponent<Hand>();
  39.             //spawn hand collider and link it to us
  40.            
  41.             handCollider = ((GameObject)Instantiate(handColliderPrefab.gameObject)).GetComponent<HandCollider>();
  42.             Vector3 localPosition = handCollider.transform.localPosition;
  43.             Quaternion localRotation = handCollider.transform.localRotation;
  44.  
  45.             handCollider.transform.parent = Player.instance.transform;
  46.             handCollider.transform.localPosition = localPosition;
  47.             handCollider.transform.localRotation = localRotation;
  48.             handCollider.hand = this;
  49.  
  50.             GetComponent<SteamVR_Behaviour_Pose>().onTransformUpdated.AddListener(UpdateHand);
  51.         }
  52.  
  53.         // cached transformations
  54.         Matrix4x4 wristToRoot;
  55.         Matrix4x4 rootToArmature;
  56.         Matrix4x4 wristToArmature;
  57.  
  58.         Vector3 targetPosition = Vector3.zero;
  59.         Quaternion targetRotation = Quaternion.identity;
  60.  
  61.         //bones
  62.         const int wristBone = SteamVR_Skeleton_JointIndexes.wrist;
  63.         const int rootBone = SteamVR_Skeleton_JointIndexes.root;
  64.  
  65.         private void FixedUpdate()
  66.         {
  67.             if (hand.skeleton == null) return;
  68.             initialized = true;
  69.  
  70.             UpdateCenterPoint();
  71.  
  72.             handCollider.MoveTo(targetPosition, targetRotation);
  73.  
  74.             if ((handCollider.transform.position - targetPosition).sqrMagnitude > handResetDistance * handResetDistance)
  75.                 handCollider.TeleportTo(targetPosition, targetRotation);
  76.  
  77.             UpdateFingertips();
  78.         }
  79.  
  80.         private void UpdateCenterPoint()
  81.         {
  82.             Vector3 offset = hand.skeleton.GetBonePosition(SteamVR_Skeleton_JointIndexes.middleProximal) - hand.skeleton.GetBonePosition(SteamVR_Skeleton_JointIndexes.root);
  83.             if (hand.HasSkeleton())
  84.             {
  85.                 handCollider.SetCenterPoint(hand.skeleton.transform.position + offset);
  86.             }
  87.         }
  88.  
  89.         Collider[] clearanceBuffer = new Collider[1];
  90.  
  91.         private void UpdatePositions()
  92.         {
  93.             // disable collisions when holding something
  94.             if (hand.currentAttachedObject != null)
  95.             {
  96.                 collisionsEnabled = false;
  97.             }
  98.             else
  99.             {
  100.                 // wait for area to become clear before reenabling collisions
  101.                 if (!collisionsEnabled)
  102.                 {
  103.                     collisionsEnabled = true;
  104.                 }
  105.             }
  106.  
  107.             handCollider.SetCollisionDetectionEnabled(collisionsEnabled);
  108.  
  109.             if (hand.skeleton == null) return;
  110.             initialized = true;
  111.  
  112.             // get the desired pose of the wrist in world space. Can't get the wrist bone transform, as this is affected by the resulting physics.
  113.  
  114.             wristToRoot = Matrix4x4.TRS(ProcessPos(wristBone, hand.skeleton.GetBone(wristBone).localPosition),
  115.                 ProcessRot(wristBone, hand.skeleton.GetBone(wristBone).localRotation),
  116.                 Vector3.one).inverse;
  117.  
  118.             rootToArmature = Matrix4x4.TRS(ProcessPos(rootBone, hand.skeleton.GetBone(rootBone).localPosition),
  119.                 ProcessRot(rootBone, hand.skeleton.GetBone(rootBone).localRotation),
  120.                 Vector3.one).inverse;
  121.  
  122.             wristToArmature = (wristToRoot * rootToArmature).inverse;
  123.  
  124.             // step up through virtual transform hierarchy and into world space
  125.             targetPosition = transform.TransformPoint(wristToArmature.MultiplyPoint3x4(Vector3.zero));
  126.  
  127.             targetRotation = transform.rotation * wristToArmature.GetRotation();
  128.  
  129.  
  130.             //bypass physics when game paused
  131.            
  132.             /*
  133.             if (Time.timeScale == 0)
  134.             {
  135.                 handCollider.TeleportTo(targetPosition, targetRotation);
  136.             }
  137.             */
  138.         }
  139.  
  140.         Transform wrist;
  141.  
  142.         const int thumbBone = SteamVR_Skeleton_JointIndexes.thumbDistal;
  143.         const int indexBone = SteamVR_Skeleton_JointIndexes.indexDistal;
  144.         const int middleBone = SteamVR_Skeleton_JointIndexes.middleDistal;
  145.         const int ringBone = SteamVR_Skeleton_JointIndexes.ringDistal;
  146.         const int pinkyBone = SteamVR_Skeleton_JointIndexes.pinkyDistal;
  147.  
  148.         void UpdateFingertips()
  149.         {
  150.             wrist = hand.skeleton.GetBone(SteamVR_Skeleton_JointIndexes.wrist);
  151.  
  152.             // set finger tip positions in wrist space
  153.  
  154.             for(int finger = 0; finger < 5; finger++)
  155.             {
  156.                 int tip = SteamVR_Skeleton_JointIndexes.GetBoneForFingerTip(finger);
  157.                 int bone = tip;
  158.                 for(int i = 0; i < handCollider.fingerColliders[finger].Length; i++)
  159.                 {
  160.                     bone = tip - 1 - i; // start at distal and go down
  161.                     if (handCollider.fingerColliders[finger][i] != null)
  162.                         handCollider.fingerColliders[finger][i].localPosition = wrist.InverseTransformPoint(hand.skeleton.GetBone(bone).position);
  163.                 }
  164.             }
  165.             /*
  166.             if(handCollider.tip_thumb != null)
  167.                 handCollider.tip_thumb.localPosition = wrist.InverseTransformPoint(hand.skeleton.GetBone(thumbBone).position);
  168.  
  169.             if(handCollider.tip_index != null)
  170.             handCollider.tip_index.localPosition = wrist.InverseTransformPoint(hand.skeleton.GetBone(indexBone).position);
  171.  
  172.             if(handCollider.tip_middle != null)
  173.             handCollider.tip_middle.localPosition = wrist.InverseTransformPoint(hand.skeleton.GetBone(middleBone).position);
  174.  
  175.             if(handCollider.tip_ring != null)
  176.             handCollider.tip_ring.localPosition = wrist.InverseTransformPoint(hand.skeleton.GetBone(ringBone).position);
  177.  
  178.             if (handCollider.tip_pinky != null)
  179.             handCollider.tip_pinky.localPosition = wrist.InverseTransformPoint(hand.skeleton.GetBone(pinkyBone).position);
  180.             */
  181.         }
  182.  
  183.         void UpdateHand(SteamVR_Behaviour_Pose pose, SteamVR_Input_Sources inputSource)
  184.         {
  185.             if (!initialized) return;
  186.  
  187.             UpdateCenterPoint();
  188.  
  189.             UpdatePositions();
  190.  
  191.             Quaternion offsetRotation = handCollider.transform.rotation * wristToArmature.inverse.GetRotation();
  192.  
  193.             hand.mainRenderModel.transform.rotation = offsetRotation;
  194.  
  195.             Vector3 offsetPosition = handCollider.transform.TransformPoint(wristToArmature.inverse.MultiplyPoint3x4(Vector3.zero));
  196.  
  197.             hand.mainRenderModel.transform.position = offsetPosition;
  198.  
  199.             /*
  200.             Vector3 wristPointInArmatureSpace = transform.InverseTransformPoint(handCollider.transform.position);
  201.  
  202.             Vector3 handTargetPosition =
  203.  
  204.             hand.mainRenderModel.transform.position = handTargetPosition;
  205.  
  206.             //Quaternion handTargetRotation = transform.rotation * (wristToArmature.inverse.rotation * (Quaternion.Inverse(transform.rotation) * handCollider.transform.rotation));
  207.  
  208.             //hand.mainRenderModel.transform.rotation = handTargetRotation;
  209.             */
  210.         }
  211.  
  212.         Vector3 ProcessPos(int boneIndex, Vector3 pos)
  213.         {
  214.             if(hand.skeleton.mirroring != SteamVR_Behaviour_Skeleton.MirrorType.None)
  215.             {
  216.                 return SteamVR_Behaviour_Skeleton.MirrorPosition(boneIndex, pos);
  217.             }
  218.  
  219.             return pos;
  220.         }
  221.  
  222.         Quaternion ProcessRot(int boneIndex, Quaternion rot)
  223.         {
  224.             if (hand.skeleton.mirroring != SteamVR_Behaviour_Skeleton.MirrorType.None)
  225.             {
  226.                 return SteamVR_Behaviour_Skeleton.MirrorRotation(boneIndex, rot);
  227.             }
  228.  
  229.             return rot;
  230.         }
  231.  
  232.  
  233.     }
  234. }
Add Comment
Please, Sign In to add comment