Advertisement
Guest User

Gorilla Tag Hit Sounds and Vibration

a guest
May 11th, 2022
2,394
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.46 KB | None | 0 0
  1. namespace GorillaLocomotion
  2. {
  3. using System.Collections;
  4. using UnityEngine;
  5. using UnityEngine.XR;
  6.  
  7. public class Player : MonoBehaviour
  8. {
  9. private static Player _instance;
  10.  
  11. public static Player Instance { get { return _instance; } }
  12.  
  13. public SphereCollider headCollider;
  14. public CapsuleCollider bodyCollider;
  15.  
  16. public Transform leftHandFollower;
  17. public Transform rightHandFollower;
  18.  
  19. public Transform rightHandTransform;
  20. public Transform leftHandTransform;
  21.  
  22. private Vector3 lastLeftHandPosition;
  23. private Vector3 lastRightHandPosition;
  24. private Vector3 lastHeadPosition;
  25.  
  26. private Rigidbody playerRigidBody;
  27.  
  28. public int velocityHistorySize;
  29. public float maxArmLength = 1.5f;
  30. public float unStickDistance = 1f;
  31.  
  32. public float velocityLimit;
  33. public float maxJumpSpeed;
  34. public float jumpMultiplier;
  35. public float minimumRaycastDistance = 0.05f;
  36. public float defaultSlideFactor = 0.03f;
  37. public float defaultPrecision = 0.995f;
  38.  
  39. private Vector3[] velocityHistory;
  40. private int velocityIndex;
  41. private Vector3 currentVelocity;
  42. private Vector3 denormalizedVelocityAverage;
  43. private bool jumpHandIsLeft;
  44. private Vector3 lastPosition;
  45.  
  46. public Vector3 rightHandOffset;
  47. public Vector3 leftHandOffset;
  48.  
  49. public LayerMask locomotionEnabledLayers;
  50.  
  51. public bool wasLeftHandTouching;
  52. public bool wasRightHandTouching;
  53.  
  54. public bool disableMovement = false;
  55.  
  56. public AudioSource HitSound;
  57.  
  58. public float hapticWaitSeconds = 0.05f;
  59.  
  60. public float vibrationAmmount = 0.15f;
  61.  
  62. private void Awake()
  63. {
  64. if (_instance != null && _instance != this)
  65. {
  66. Destroy(gameObject);
  67. }
  68. else
  69. {
  70. _instance = this;
  71. }
  72.  
  73. InitializeValues();
  74. }
  75.  
  76. public void InitializeValues()
  77. {
  78. playerRigidBody = GetComponent<Rigidbody>();
  79. velocityHistory = new Vector3[velocityHistorySize];
  80. lastLeftHandPosition = leftHandFollower.transform.position;
  81. lastRightHandPosition = rightHandFollower.transform.position;
  82. lastHeadPosition = headCollider.transform.position;
  83. velocityIndex = 0;
  84. lastPosition = transform.position;
  85. }
  86.  
  87. private Vector3 CurrentLeftHandPosition()
  88. {
  89. if ((PositionWithOffset(leftHandTransform, leftHandOffset) - headCollider.transform.position).magnitude < maxArmLength)
  90. {
  91. return PositionWithOffset(leftHandTransform, leftHandOffset);
  92. }
  93. else
  94. {
  95. return headCollider.transform.position + (PositionWithOffset(leftHandTransform, leftHandOffset) - headCollider.transform.position).normalized * maxArmLength;
  96. }
  97. }
  98.  
  99. private Vector3 CurrentRightHandPosition()
  100. {
  101. if ((PositionWithOffset(rightHandTransform, rightHandOffset) - headCollider.transform.position).magnitude < maxArmLength)
  102. {
  103. return PositionWithOffset(rightHandTransform, rightHandOffset);
  104. }
  105. else
  106. {
  107. return headCollider.transform.position + (PositionWithOffset(rightHandTransform, rightHandOffset) - headCollider.transform.position).normalized * maxArmLength;
  108. }
  109. }
  110.  
  111. private Vector3 PositionWithOffset(Transform transformToModify, Vector3 offsetVector)
  112. {
  113. return transformToModify.position + transformToModify.rotation * offsetVector;
  114. }
  115.  
  116. private void Update()
  117. {
  118. bool leftHandColliding = false;
  119. bool rightHandColliding = false;
  120. Vector3 finalPosition;
  121. Vector3 rigidBodyMovement = Vector3.zero;
  122. Vector3 firstIterationLeftHand = Vector3.zero;
  123. Vector3 firstIterationRightHand = Vector3.zero;
  124. RaycastHit hitInfo;
  125.  
  126. bodyCollider.transform.eulerAngles = new Vector3(0, headCollider.transform.eulerAngles.y, 0);
  127.  
  128. //left hand
  129.  
  130. Vector3 distanceTraveled = CurrentLeftHandPosition() - lastLeftHandPosition + Vector3.down * 2f * 9.8f * Time.deltaTime * Time.deltaTime;
  131.  
  132. leftHandFollower.localRotation = leftHandTransform.localRotation;
  133.  
  134. if (IterativeCollisionSphereCast(lastLeftHandPosition, minimumRaycastDistance, distanceTraveled, defaultPrecision, out finalPosition, true))
  135. {
  136. //this lets you stick to the position you touch, as long as you keep touching the surface this will be the zero point for that hand
  137. if (wasLeftHandTouching)
  138. {
  139. firstIterationLeftHand = lastLeftHandPosition - CurrentLeftHandPosition();
  140. }
  141. else
  142. {
  143. firstIterationLeftHand = finalPosition - CurrentLeftHandPosition();
  144.  
  145. StartVibration(true, vibrationAmmount, 0.15f);
  146. HitSound.Play();
  147. }
  148. playerRigidBody.velocity = Vector3.zero;
  149.  
  150. leftHandColliding = true;
  151. }
  152.  
  153. //right hand
  154.  
  155. distanceTraveled = CurrentRightHandPosition() - lastRightHandPosition + Vector3.down * 2f * 9.8f * Time.deltaTime * Time.deltaTime;
  156.  
  157. rightHandFollower.localRotation = rightHandTransform.localRotation;
  158.  
  159. if (IterativeCollisionSphereCast(lastRightHandPosition, minimumRaycastDistance, distanceTraveled, defaultPrecision, out finalPosition, true))
  160. {
  161. if (wasRightHandTouching)
  162. {
  163. firstIterationRightHand = lastRightHandPosition - CurrentRightHandPosition();
  164. }
  165. else
  166. {
  167. firstIterationRightHand = finalPosition - CurrentRightHandPosition();
  168.  
  169. StartVibration(false, vibrationAmmount, 0.15f);
  170. HitSound.Play();
  171. }
  172.  
  173. playerRigidBody.velocity = Vector3.zero;
  174.  
  175. rightHandColliding = true;
  176. }
  177.  
  178. //average or add
  179.  
  180. if ((leftHandColliding || wasLeftHandTouching) && (rightHandColliding || wasRightHandTouching))
  181. {
  182. //this lets you grab stuff with both hands at the same time
  183. rigidBodyMovement = (firstIterationLeftHand + firstIterationRightHand) / 2;
  184. }
  185. else
  186. {
  187. rigidBodyMovement = firstIterationLeftHand + firstIterationRightHand;
  188. }
  189.  
  190. //check valid head movement
  191.  
  192. if (IterativeCollisionSphereCast(lastHeadPosition, headCollider.radius, headCollider.transform.position + rigidBodyMovement - lastHeadPosition, defaultPrecision, out finalPosition, false))
  193. {
  194. rigidBodyMovement = finalPosition - lastHeadPosition;
  195. //last check to make sure the head won't phase through geometry
  196. if (Physics.Raycast(lastHeadPosition, headCollider.transform.position - lastHeadPosition + rigidBodyMovement, out hitInfo, (headCollider.transform.position - lastHeadPosition + rigidBodyMovement).magnitude + headCollider.radius * defaultPrecision * 0.999f, locomotionEnabledLayers.value))
  197. {
  198. rigidBodyMovement = lastHeadPosition - headCollider.transform.position;
  199. }
  200. }
  201.  
  202. if (rigidBodyMovement != Vector3.zero)
  203. {
  204. transform.position = transform.position + rigidBodyMovement;
  205. }
  206.  
  207. lastHeadPosition = headCollider.transform.position;
  208.  
  209. //do final left hand position
  210.  
  211. distanceTraveled = CurrentLeftHandPosition() - lastLeftHandPosition;
  212.  
  213. if (IterativeCollisionSphereCast(lastLeftHandPosition, minimumRaycastDistance, distanceTraveled, defaultPrecision, out finalPosition, !((leftHandColliding || wasLeftHandTouching) && (rightHandColliding || wasRightHandTouching))))
  214. {
  215. lastLeftHandPosition = finalPosition;
  216. leftHandColliding = true;
  217. }
  218. else
  219. {
  220. lastLeftHandPosition = CurrentLeftHandPosition();
  221. }
  222.  
  223. //do final right hand position
  224.  
  225. distanceTraveled = CurrentRightHandPosition() - lastRightHandPosition;
  226.  
  227. if (IterativeCollisionSphereCast(lastRightHandPosition, minimumRaycastDistance, distanceTraveled, defaultPrecision, out finalPosition, !((leftHandColliding || wasLeftHandTouching) && (rightHandColliding || wasRightHandTouching))))
  228. {
  229. lastRightHandPosition = finalPosition;
  230. rightHandColliding = true;
  231. }
  232. else
  233. {
  234. lastRightHandPosition = CurrentRightHandPosition();
  235. }
  236.  
  237. StoreVelocities();
  238.  
  239. if ((rightHandColliding || leftHandColliding) && !disableMovement)
  240. {
  241. if (denormalizedVelocityAverage.magnitude > velocityLimit)
  242. {
  243. if (denormalizedVelocityAverage.magnitude * jumpMultiplier > maxJumpSpeed)
  244. {
  245. playerRigidBody.velocity = denormalizedVelocityAverage.normalized * maxJumpSpeed;
  246. }
  247. else
  248. {
  249. playerRigidBody.velocity = jumpMultiplier * denormalizedVelocityAverage;
  250. }
  251. }
  252. }
  253.  
  254. //check to see if left hand is stuck and we should unstick it
  255.  
  256. if (leftHandColliding && (CurrentLeftHandPosition() - lastLeftHandPosition).magnitude > unStickDistance && !Physics.SphereCast(headCollider.transform.position, minimumRaycastDistance * defaultPrecision, CurrentLeftHandPosition() - headCollider.transform.position, out hitInfo, (CurrentLeftHandPosition() - headCollider.transform.position).magnitude - minimumRaycastDistance, locomotionEnabledLayers.value))
  257. {
  258. lastLeftHandPosition = CurrentLeftHandPosition();
  259. leftHandColliding = false;
  260. }
  261.  
  262. //check to see if right hand is stuck and we should unstick it
  263.  
  264. if (rightHandColliding && (CurrentRightHandPosition() - lastRightHandPosition).magnitude > unStickDistance && !Physics.SphereCast(headCollider.transform.position, minimumRaycastDistance * defaultPrecision, CurrentRightHandPosition() - headCollider.transform.position, out hitInfo, (CurrentRightHandPosition() - headCollider.transform.position).magnitude - minimumRaycastDistance, locomotionEnabledLayers.value))
  265. {
  266. lastRightHandPosition = CurrentRightHandPosition();
  267. rightHandColliding = false;
  268. }
  269.  
  270. leftHandFollower.position = lastLeftHandPosition;
  271. rightHandFollower.position = lastRightHandPosition;
  272.  
  273. wasLeftHandTouching = leftHandColliding;
  274. wasRightHandTouching = rightHandColliding;
  275. }
  276.  
  277. private bool IterativeCollisionSphereCast(Vector3 startPosition, float sphereRadius, Vector3 movementVector, float precision, out Vector3 endPosition, bool singleHand)
  278. {
  279. RaycastHit hitInfo;
  280. Vector3 movementToProjectedAboveCollisionPlane;
  281. Surface gorillaSurface;
  282. float slipPercentage;
  283. //first spherecast from the starting position to the final position
  284. if (CollisionsSphereCast(startPosition, sphereRadius * precision, movementVector, precision, out endPosition, out hitInfo))
  285. {
  286. //if we hit a surface, do a bit of a slide. this makes it so if you grab with two hands you don't stick 100%, and if you're pushing along a surface while braced with your head, your hand will slide a bit
  287.  
  288. //take the surface normal that we hit, then along that plane, do a spherecast to a position a small distance away to account for moving perpendicular to that surface
  289. Vector3 firstPosition = endPosition;
  290. gorillaSurface = hitInfo.collider.GetComponent<Surface>();
  291. slipPercentage = gorillaSurface != null ? gorillaSurface.slipPercentage : (!singleHand ? defaultSlideFactor : 0.001f);
  292. movementToProjectedAboveCollisionPlane = Vector3.ProjectOnPlane(startPosition + movementVector - firstPosition, hitInfo.normal) * slipPercentage;
  293. if (CollisionsSphereCast(endPosition, sphereRadius, movementToProjectedAboveCollisionPlane, precision * precision, out endPosition, out hitInfo))
  294. {
  295. //if we hit trying to move perpendicularly, stop there and our end position is the final spot we hit
  296. return true;
  297. }
  298. //if not, try to move closer towards the true point to account for the fact that the movement along the normal of the hit could have moved you away from the surface
  299. else if (CollisionsSphereCast(movementToProjectedAboveCollisionPlane + firstPosition, sphereRadius, startPosition + movementVector - (movementToProjectedAboveCollisionPlane + firstPosition), precision * precision * precision, out endPosition, out hitInfo))
  300. {
  301. //if we hit, then return the spot we hit
  302. return true;
  303. }
  304. else
  305. {
  306. //this shouldn't really happe, since this means that the sliding motion got you around some corner or something and let you get to your final point. back off because something strange happened, so just don't do the slide
  307. endPosition = firstPosition;
  308. return true;
  309. }
  310. }
  311. //as kind of a sanity check, try a smaller spherecast. this accounts for times when the original spherecast was already touching a surface so it didn't trigger correctly
  312. else if (CollisionsSphereCast(startPosition, sphereRadius * precision * 0.66f, movementVector.normalized * (movementVector.magnitude + sphereRadius * precision * 0.34f), precision * 0.66f, out endPosition, out hitInfo))
  313. {
  314. endPosition = startPosition;
  315. return true;
  316. }
  317. else
  318. {
  319. endPosition = Vector3.zero;
  320. return false;
  321. }
  322. }
  323.  
  324. private bool CollisionsSphereCast(Vector3 startPosition, float sphereRadius, Vector3 movementVector, float precision, out Vector3 finalPosition, out RaycastHit hitInfo)
  325. {
  326. //kind of like a souped up spherecast. includes checks to make sure that the sphere we're using, if it touches a surface, is pushed away the correct distance (the original sphereradius distance). since you might
  327. //be pushing into sharp corners, this might not always be valid, so that's what the extra checks are for
  328.  
  329. //initial spherecase
  330. RaycastHit innerHit;
  331. if (Physics.SphereCast(startPosition, sphereRadius * precision, movementVector, out hitInfo, movementVector.magnitude + sphereRadius * (1 - precision), locomotionEnabledLayers.value))
  332. {
  333. //if we hit, we're trying to move to a position a sphereradius distance from the normal
  334. finalPosition = hitInfo.point + hitInfo.normal * sphereRadius;
  335.  
  336. //check a spherecase from the original position to the intended final position
  337. if (Physics.SphereCast(startPosition, sphereRadius * precision * precision, finalPosition - startPosition, out innerHit, (finalPosition - startPosition).magnitude + sphereRadius * (1 - precision * precision), locomotionEnabledLayers.value))
  338. {
  339. finalPosition = startPosition + (finalPosition - startPosition).normalized * Mathf.Max(0, hitInfo.distance - sphereRadius * (1f - precision * precision));
  340. hitInfo = innerHit;
  341. }
  342. //bonus raycast check to make sure that something odd didn't happen with the spherecast. helps prevent clipping through geometry
  343. else if (Physics.Raycast(startPosition, finalPosition - startPosition, out innerHit, (finalPosition - startPosition).magnitude + sphereRadius * precision * precision * 0.999f, locomotionEnabledLayers.value))
  344. {
  345. finalPosition = startPosition;
  346. hitInfo = innerHit;
  347. return true;
  348. }
  349. return true;
  350. }
  351. //anti-clipping through geometry check
  352. else if (Physics.Raycast(startPosition, movementVector, out hitInfo, movementVector.magnitude + sphereRadius * precision * 0.999f, locomotionEnabledLayers.value))
  353. {
  354. finalPosition = startPosition;
  355. return true;
  356. }
  357. else
  358. {
  359. finalPosition = Vector3.zero;
  360. return false;
  361. }
  362. }
  363.  
  364. public bool IsHandTouching(bool forLeftHand)
  365. {
  366. if (forLeftHand)
  367. {
  368. return wasLeftHandTouching;
  369. }
  370. else
  371. {
  372. return wasRightHandTouching;
  373. }
  374. }
  375.  
  376. public void Turn(float degrees)
  377. {
  378. transform.RotateAround(headCollider.transform.position, transform.up, degrees);
  379. denormalizedVelocityAverage = Quaternion.Euler(0, degrees, 0) * denormalizedVelocityAverage;
  380. for (int i = 0; i < velocityHistory.Length; i++)
  381. {
  382. velocityHistory[i] = Quaternion.Euler(0, degrees, 0) * velocityHistory[i];
  383. }
  384. }
  385.  
  386. public void StartVibration(bool forLeftController, float amplitude, float duration)
  387. {
  388. base.StartCoroutine(this.HapticPulses(forLeftController, amplitude, duration));
  389. }
  390.  
  391. // Token: 0x06000315 RID: 789 RVA: 0x00016512 File Offset: 0x00014712
  392. private IEnumerator HapticPulses(bool forLeftController, float amplitude, float duration)
  393. {
  394. float startTime = Time.time;
  395. uint channel = 0U;
  396. InputDevice device;
  397. if (forLeftController)
  398. {
  399. device = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
  400. }
  401. else
  402. {
  403. device = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
  404. }
  405. while (Time.time < startTime + duration)
  406. {
  407. device.SendHapticImpulse(channel, amplitude, this.hapticWaitSeconds);
  408. yield return new WaitForSeconds(this.hapticWaitSeconds * 0.9f);
  409. }
  410. yield break;
  411. }
  412.  
  413. private void StoreVelocities()
  414. {
  415. velocityIndex = (velocityIndex + 1) % velocityHistorySize;
  416. Vector3 oldestVelocity = velocityHistory[velocityIndex];
  417. currentVelocity = (transform.position - lastPosition) / Time.deltaTime;
  418. denormalizedVelocityAverage += (currentVelocity - oldestVelocity) / (float)velocityHistorySize;
  419. velocityHistory[velocityIndex] = currentVelocity;
  420. lastPosition = transform.position;
  421. }
  422.  
  423. }
  424. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement