Player.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Player interface used to query HMD transforms and VR hands
  4. //
  5. //=============================================================================
  6. using UnityEngine;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. namespace Valve.VR.InteractionSystem
  10. {
  11. //-------------------------------------------------------------------------
  12. // Singleton representing the local VR player/user, with methods for getting
  13. // the player's hands, head, tracking origin, and guesses for various properties.
  14. //-------------------------------------------------------------------------
  15. public class Player : MonoBehaviour
  16. {
  17. [Tooltip( "Virtual transform corresponding to the meatspace tracking origin. Devices are tracked relative to this." )]
  18. public Transform trackingOriginTransform;
  19. [Tooltip( "List of possible transforms for the head/HMD, including the no-SteamVR fallback camera." )]
  20. public Transform[] hmdTransforms;
  21. [Tooltip( "List of possible Hands, including no-SteamVR fallback Hands." )]
  22. public Hand[] hands;
  23. [Tooltip( "Reference to the physics collider that follows the player's HMD position." )]
  24. public Collider headCollider;
  25. [Tooltip( "These objects are enabled when SteamVR is available" )]
  26. public GameObject rigSteamVR;
  27. [Tooltip( "These objects are enabled when SteamVR is not available, or when the user toggles out of VR" )]
  28. public GameObject rig2DFallback;
  29. [Tooltip( "The audio listener for this player" )]
  30. public Transform audioListener;
  31. [Tooltip("This action lets you know when the player has placed the headset on their head")]
  32. public SteamVR_Action_Boolean headsetOnHead = SteamVR_Input.GetBooleanAction("HeadsetOnHead");
  33. public bool allowToggleTo2D = true;
  34. //-------------------------------------------------
  35. // Singleton instance of the Player. Only one can exist at a time.
  36. //-------------------------------------------------
  37. private static Player _instance;
  38. public static Player instance
  39. {
  40. get
  41. {
  42. if ( _instance == null )
  43. {
  44. _instance = FindObjectOfType<Player>();
  45. }
  46. return _instance;
  47. }
  48. }
  49. //-------------------------------------------------
  50. // Get the number of active Hands.
  51. //-------------------------------------------------
  52. public int handCount
  53. {
  54. get
  55. {
  56. int count = 0;
  57. for ( int i = 0; i < hands.Length; i++ )
  58. {
  59. if ( hands[i].gameObject.activeInHierarchy )
  60. {
  61. count++;
  62. }
  63. }
  64. return count;
  65. }
  66. }
  67. //-------------------------------------------------
  68. // Get the i-th active Hand.
  69. //
  70. // i - Zero-based index of the active Hand to get
  71. //-------------------------------------------------
  72. public Hand GetHand( int i )
  73. {
  74. for ( int j = 0; j < hands.Length; j++ )
  75. {
  76. if ( !hands[j].gameObject.activeInHierarchy )
  77. {
  78. continue;
  79. }
  80. if ( i > 0 )
  81. {
  82. i--;
  83. continue;
  84. }
  85. return hands[j];
  86. }
  87. return null;
  88. }
  89. //-------------------------------------------------
  90. public Hand leftHand
  91. {
  92. get
  93. {
  94. for ( int j = 0; j < hands.Length; j++ )
  95. {
  96. if ( !hands[j].gameObject.activeInHierarchy )
  97. {
  98. continue;
  99. }
  100. if ( hands[j].handType != SteamVR_Input_Sources.LeftHand)
  101. {
  102. continue;
  103. }
  104. return hands[j];
  105. }
  106. return null;
  107. }
  108. }
  109. //-------------------------------------------------
  110. public Hand rightHand
  111. {
  112. get
  113. {
  114. for ( int j = 0; j < hands.Length; j++ )
  115. {
  116. if ( !hands[j].gameObject.activeInHierarchy )
  117. {
  118. continue;
  119. }
  120. if ( hands[j].handType != SteamVR_Input_Sources.RightHand)
  121. {
  122. continue;
  123. }
  124. return hands[j];
  125. }
  126. return null;
  127. }
  128. }
  129. //-------------------------------------------------
  130. // Get Player scale. Assumes it is scaled equally on all axes.
  131. //-------------------------------------------------
  132. public float scale
  133. {
  134. get
  135. {
  136. return transform.lossyScale.x;
  137. }
  138. }
  139. //-------------------------------------------------
  140. // Get the HMD transform. This might return the fallback camera transform if SteamVR is unavailable or disabled.
  141. //-------------------------------------------------
  142. public Transform hmdTransform
  143. {
  144. get
  145. {
  146. if (hmdTransforms != null)
  147. {
  148. for (int i = 0; i < hmdTransforms.Length; i++)
  149. {
  150. if (hmdTransforms[i].gameObject.activeInHierarchy)
  151. return hmdTransforms[i];
  152. }
  153. }
  154. return null;
  155. }
  156. }
  157. //-------------------------------------------------
  158. // Height of the eyes above the ground - useful for estimating player height.
  159. //-------------------------------------------------
  160. public float eyeHeight
  161. {
  162. get
  163. {
  164. Transform hmd = hmdTransform;
  165. if ( hmd )
  166. {
  167. Vector3 eyeOffset = Vector3.Project( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up );
  168. return eyeOffset.magnitude / trackingOriginTransform.lossyScale.x;
  169. }
  170. return 0.0f;
  171. }
  172. }
  173. //-------------------------------------------------
  174. // Guess for the world-space position of the player's feet, directly beneath the HMD.
  175. //-------------------------------------------------
  176. public Vector3 feetPositionGuess
  177. {
  178. get
  179. {
  180. Transform hmd = hmdTransform;
  181. if ( hmd )
  182. {
  183. return trackingOriginTransform.position + Vector3.ProjectOnPlane( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up );
  184. }
  185. return trackingOriginTransform.position;
  186. }
  187. }
  188. //-------------------------------------------------
  189. // Guess for the world-space direction of the player's hips/torso. This is effectively just the gaze direction projected onto the floor plane.
  190. //-------------------------------------------------
  191. public Vector3 bodyDirectionGuess
  192. {
  193. get
  194. {
  195. Transform hmd = hmdTransform;
  196. if ( hmd )
  197. {
  198. Vector3 direction = Vector3.ProjectOnPlane( hmd.forward, trackingOriginTransform.up );
  199. if ( Vector3.Dot( hmd.up, trackingOriginTransform.up ) < 0.0f )
  200. {
  201. // The HMD is upside-down. Either
  202. // -The player is bending over backwards
  203. // -The player is bent over looking through their legs
  204. direction = -direction;
  205. }
  206. return direction;
  207. }
  208. return trackingOriginTransform.forward;
  209. }
  210. }
  211. //-------------------------------------------------
  212. private void Awake()
  213. {
  214. if ( trackingOriginTransform == null )
  215. {
  216. trackingOriginTransform = this.transform;
  217. }
  218. }
  219. //-------------------------------------------------
  220. private IEnumerator Start()
  221. {
  222. _instance = this;
  223. while (SteamVR.initializedState == SteamVR.InitializedStates.None || SteamVR.initializedState == SteamVR.InitializedStates.Initializing)
  224. yield return null;
  225. if ( SteamVR.instance != null )
  226. {
  227. ActivateRig( rigSteamVR );
  228. }
  229. else
  230. {
  231. #if !HIDE_DEBUG_UI
  232. ActivateRig( rig2DFallback );
  233. #endif
  234. }
  235. }
  236. protected virtual void Update()
  237. {
  238. if (SteamVR.initializedState != SteamVR.InitializedStates.InitializeSuccess)
  239. return;
  240. if (headsetOnHead != null)
  241. {
  242. if (headsetOnHead.GetStateDown(SteamVR_Input_Sources.Head))
  243. {
  244. Debug.Log("<b>SteamVR Interaction System</b> Headset placed on head");
  245. }
  246. else if (headsetOnHead.GetStateUp(SteamVR_Input_Sources.Head))
  247. {
  248. Debug.Log("<b>SteamVR Interaction System</b> Headset removed");
  249. }
  250. }
  251. }
  252. //-------------------------------------------------
  253. void OnDrawGizmos()
  254. {
  255. if ( this != instance )
  256. {
  257. return;
  258. }
  259. //NOTE: These gizmo icons don't work in the plugin since the icons need to exist in a specific "Gizmos"
  260. // folder in your Asset tree. These icons are included under Core/Icons. Moving them into a
  261. // "Gizmos" folder should make them work again.
  262. Gizmos.color = Color.white;
  263. Gizmos.DrawIcon( feetPositionGuess, "vr_interaction_system_feet.png" );
  264. Gizmos.color = Color.cyan;
  265. Gizmos.DrawLine( feetPositionGuess, feetPositionGuess + trackingOriginTransform.up * eyeHeight );
  266. // Body direction arrow
  267. Gizmos.color = Color.blue;
  268. Vector3 bodyDirection = bodyDirectionGuess;
  269. Vector3 bodyDirectionTangent = Vector3.Cross( trackingOriginTransform.up, bodyDirection );
  270. Vector3 startForward = feetPositionGuess + trackingOriginTransform.up * eyeHeight * 0.75f;
  271. Vector3 endForward = startForward + bodyDirection * 0.33f;
  272. Gizmos.DrawLine( startForward, endForward );
  273. Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection + bodyDirectionTangent ) );
  274. Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection - bodyDirectionTangent ) );
  275. Gizmos.color = Color.red;
  276. int count = handCount;
  277. for ( int i = 0; i < count; i++ )
  278. {
  279. Hand hand = GetHand( i );
  280. if ( hand.handType == SteamVR_Input_Sources.LeftHand)
  281. {
  282. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand.png" );
  283. }
  284. else if ( hand.handType == SteamVR_Input_Sources.RightHand)
  285. {
  286. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand.png" );
  287. }
  288. else
  289. {
  290. /*
  291. Hand.HandType guessHandType = hand.currentHandType;
  292. if ( guessHandType == Hand.HandType.Left )
  293. {
  294. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand_question.png" );
  295. }
  296. else if ( guessHandType == Hand.HandType.Right )
  297. {
  298. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand_question.png" );
  299. }
  300. else
  301. {
  302. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_unknown_hand.png" );
  303. }
  304. */
  305. }
  306. }
  307. }
  308. //-------------------------------------------------
  309. public void Draw2DDebug()
  310. {
  311. if ( !allowToggleTo2D )
  312. return;
  313. if ( !SteamVR.active )
  314. return;
  315. int width = 100;
  316. int height = 25;
  317. int left = Screen.width / 2 - width / 2;
  318. int top = Screen.height - height - 10;
  319. string text = ( rigSteamVR.activeSelf ) ? "2D Debug" : "VR";
  320. if ( GUI.Button( new Rect( left, top, width, height ), text ) )
  321. {
  322. if ( rigSteamVR.activeSelf )
  323. {
  324. ActivateRig( rig2DFallback );
  325. }
  326. else
  327. {
  328. ActivateRig( rigSteamVR );
  329. }
  330. }
  331. }
  332. //-------------------------------------------------
  333. private void ActivateRig( GameObject rig )
  334. {
  335. rigSteamVR.SetActive( rig == rigSteamVR );
  336. rig2DFallback.SetActive( rig == rig2DFallback );
  337. if ( audioListener )
  338. {
  339. audioListener.transform.parent = hmdTransform;
  340. audioListener.transform.localPosition = Vector3.zero;
  341. audioListener.transform.localRotation = Quaternion.identity;
  342. }
  343. }
  344. //-------------------------------------------------
  345. public void PlayerShotSelf()
  346. {
  347. //Do something appropriate here
  348. }
  349. }
  350. }