SteamVR_Teleporter.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using UnityEngine;
  2. using System.Collections;
  3. public class SteamVR_Teleporter : MonoBehaviour
  4. {
  5. public enum TeleportType
  6. {
  7. TeleportTypeUseTerrain,
  8. TeleportTypeUseCollider,
  9. TeleportTypeUseZeroY
  10. }
  11. public bool teleportOnClick = false;
  12. public TeleportType teleportType = TeleportType.TeleportTypeUseZeroY;
  13. Transform reference
  14. {
  15. get
  16. {
  17. var top = SteamVR_Render.Top();
  18. return (top != null) ? top.origin : null;
  19. }
  20. }
  21. void Start()
  22. {
  23. var trackedController = GetComponent<SteamVR_TrackedController>();
  24. if (trackedController == null)
  25. {
  26. trackedController = gameObject.AddComponent<SteamVR_TrackedController>();
  27. }
  28. trackedController.TriggerClicked += new ClickedEventHandler(DoClick);
  29. if (teleportType == TeleportType.TeleportTypeUseTerrain)
  30. {
  31. // Start the player at the level of the terrain
  32. var t = reference;
  33. if (t != null)
  34. t.position = new Vector3(t.position.x, Terrain.activeTerrain.SampleHeight(t.position), t.position.z);
  35. }
  36. }
  37. void DoClick(object sender, ClickedEventArgs e)
  38. {
  39. if (teleportOnClick)
  40. {
  41. // First get the current Transform of the the reference space (i.e. the Play Area, e.g. CameraRig prefab)
  42. var t = reference;
  43. if (t == null)
  44. return;
  45. // Get the current Y position of the reference space
  46. float refY = t.position.y;
  47. // Create a plane at the Y position of the Play Area
  48. // Then create a Ray from the origin of the controller in the direction that the controller is pointing
  49. Plane plane = new Plane(Vector3.up, -refY);
  50. Ray ray = new Ray(this.transform.position, transform.forward);
  51. // Set defaults
  52. bool hasGroundTarget = false;
  53. float dist = 0f;
  54. if (teleportType == TeleportType.TeleportTypeUseTerrain) // If we picked to use the terrain
  55. {
  56. RaycastHit hitInfo;
  57. TerrainCollider tc = Terrain.activeTerrain.GetComponent<TerrainCollider>();
  58. hasGroundTarget = tc.Raycast(ray, out hitInfo, 1000f);
  59. dist = hitInfo.distance;
  60. }
  61. else if (teleportType == TeleportType.TeleportTypeUseCollider) // If we picked to use the collider
  62. {
  63. RaycastHit hitInfo;
  64. hasGroundTarget = Physics.Raycast(ray, out hitInfo);
  65. dist = hitInfo.distance;
  66. }
  67. else // If we're just staying flat on the current Y axis
  68. {
  69. // Intersect a ray with the plane that was created earlier
  70. // and output the distance along the ray that it intersects
  71. hasGroundTarget = plane.Raycast(ray, out dist);
  72. }
  73. if (hasGroundTarget)
  74. {
  75. // Get the current Camera (head) position on the ground relative to the world
  76. Vector3 headPosOnGround = new Vector3(SteamVR_Render.Top().head.position.x, refY, SteamVR_Render.Top().head.position.z);
  77. // We need to translate the reference space along the same vector
  78. // that is between the head's position on the ground and the intersection point on the ground
  79. // i.e. intersectionPoint - headPosOnGround = translateVector
  80. // currentReferencePosition + translateVector = finalPosition
  81. t.position = t.position + (ray.origin + (ray.direction * dist)) - headPosOnGround;
  82. }
  83. }
  84. }
  85. }