Player.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  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. #if OPENVR_XR_API && UNITY_LEGACY_INPUT_HELPERS
  219. if (hmdTransforms != null)
  220. {
  221. foreach (var hmd in hmdTransforms)
  222. {
  223. if (hmd.GetComponent<UnityEngine.SpatialTracking.TrackedPoseDriver>() == null)
  224. hmd.gameObject.AddComponent<UnityEngine.SpatialTracking.TrackedPoseDriver>();
  225. }
  226. }
  227. #endif
  228. }
  229. //-------------------------------------------------
  230. private IEnumerator Start()
  231. {
  232. _instance = this;
  233. while (SteamVR.initializedState == SteamVR.InitializedStates.None || SteamVR.initializedState == SteamVR.InitializedStates.Initializing)
  234. yield return null;
  235. if ( SteamVR.instance != null )
  236. {
  237. ActivateRig( rigSteamVR );
  238. }
  239. else
  240. {
  241. #if !HIDE_DEBUG_UI
  242. ActivateRig( rig2DFallback );
  243. #endif
  244. }
  245. }
  246. protected virtual void Update()
  247. {
  248. if (SteamVR.initializedState != SteamVR.InitializedStates.InitializeSuccess)
  249. return;
  250. if (headsetOnHead != null)
  251. {
  252. if (headsetOnHead.GetStateDown(SteamVR_Input_Sources.Head))
  253. {
  254. Debug.Log("<b>SteamVR Interaction System</b> Headset placed on head");
  255. }
  256. else if (headsetOnHead.GetStateUp(SteamVR_Input_Sources.Head))
  257. {
  258. Debug.Log("<b>SteamVR Interaction System</b> Headset removed");
  259. }
  260. }
  261. }
  262. //-------------------------------------------------
  263. void OnDrawGizmos()
  264. {
  265. if ( this != instance )
  266. {
  267. return;
  268. }
  269. //NOTE: These gizmo icons don't work in the plugin since the icons need to exist in a specific "Gizmos"
  270. // folder in your Asset tree. These icons are included under Core/Icons. Moving them into a
  271. // "Gizmos" folder should make them work again.
  272. Gizmos.color = Color.white;
  273. Gizmos.DrawIcon( feetPositionGuess, "vr_interaction_system_feet.png" );
  274. Gizmos.color = Color.cyan;
  275. Gizmos.DrawLine( feetPositionGuess, feetPositionGuess + trackingOriginTransform.up * eyeHeight );
  276. // Body direction arrow
  277. Gizmos.color = Color.blue;
  278. Vector3 bodyDirection = bodyDirectionGuess;
  279. Vector3 bodyDirectionTangent = Vector3.Cross( trackingOriginTransform.up, bodyDirection );
  280. Vector3 startForward = feetPositionGuess + trackingOriginTransform.up * eyeHeight * 0.75f;
  281. Vector3 endForward = startForward + bodyDirection * 0.33f;
  282. Gizmos.DrawLine( startForward, endForward );
  283. Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection + bodyDirectionTangent ) );
  284. Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection - bodyDirectionTangent ) );
  285. Gizmos.color = Color.red;
  286. int count = handCount;
  287. for ( int i = 0; i < count; i++ )
  288. {
  289. Hand hand = GetHand( i );
  290. if ( hand.handType == SteamVR_Input_Sources.LeftHand)
  291. {
  292. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand.png" );
  293. }
  294. else if ( hand.handType == SteamVR_Input_Sources.RightHand)
  295. {
  296. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand.png" );
  297. }
  298. else
  299. {
  300. /*
  301. Hand.HandType guessHandType = hand.currentHandType;
  302. if ( guessHandType == Hand.HandType.Left )
  303. {
  304. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand_question.png" );
  305. }
  306. else if ( guessHandType == Hand.HandType.Right )
  307. {
  308. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand_question.png" );
  309. }
  310. else
  311. {
  312. Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_unknown_hand.png" );
  313. }
  314. */
  315. }
  316. }
  317. }
  318. //-------------------------------------------------
  319. public void Draw2DDebug()
  320. {
  321. if ( !allowToggleTo2D )
  322. return;
  323. if ( !SteamVR.active )
  324. return;
  325. int width = 100;
  326. int height = 25;
  327. int left = Screen.width / 2 - width / 2;
  328. int top = Screen.height - height - 10;
  329. string text = ( rigSteamVR.activeSelf ) ? "2D Debug" : "VR";
  330. if ( GUI.Button( new Rect( left, top, width, height ), text ) )
  331. {
  332. if ( rigSteamVR.activeSelf )
  333. {
  334. ActivateRig( rig2DFallback );
  335. }
  336. else
  337. {
  338. ActivateRig( rigSteamVR );
  339. }
  340. }
  341. }
  342. //-------------------------------------------------
  343. private void ActivateRig( GameObject rig )
  344. {
  345. rigSteamVR.SetActive( rig == rigSteamVR );
  346. rig2DFallback.SetActive( rig == rig2DFallback );
  347. if ( audioListener )
  348. {
  349. audioListener.transform.parent = hmdTransform;
  350. audioListener.transform.localPosition = Vector3.zero;
  351. audioListener.transform.localRotation = Quaternion.identity;
  352. }
  353. }
  354. //-------------------------------------------------
  355. public void PlayerShotSelf()
  356. {
  357. //Do something appropriate here
  358. }
  359. }
  360. }