|
|
//======= Copyright (c) Valve Corporation, All rights reserved. ===============
//
// Purpose: Handles all the teleport logic
//
//=============================================================================
using UnityEngine;using UnityEngine.Events;using System.Collections;
namespace Valve.VR.InteractionSystem{ //-------------------------------------------------------------------------
public class Teleport : MonoBehaviour { public SteamVR_Action_Boolean teleportAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("Teleport");
public LayerMask traceLayerMask; public LayerMask floorFixupTraceLayerMask; public float floorFixupMaximumTraceDistance = 1.0f; public Material areaVisibleMaterial; public Material areaLockedMaterial; public Material areaHighlightedMaterial; public Material pointVisibleMaterial; public Material pointLockedMaterial; public Material pointHighlightedMaterial; public Transform destinationReticleTransform; public Transform invalidReticleTransform; public GameObject playAreaPreviewCorner; public GameObject playAreaPreviewSide; public Color pointerValidColor; public Color pointerInvalidColor; public Color pointerLockedColor; public bool showPlayAreaMarker = true;
public float teleportFadeTime = 0.1f; public float meshFadeTime = 0.2f;
public float arcDistance = 10.0f;
[Header( "Effects" )] public Transform onActivateObjectTransform; public Transform onDeactivateObjectTransform; public float activateObjectTime = 1.0f; public float deactivateObjectTime = 1.0f;
[Header( "Audio Sources" )] public AudioSource pointerAudioSource; public AudioSource loopingAudioSource; public AudioSource headAudioSource; public AudioSource reticleAudioSource;
[Header( "Sounds" )] public AudioClip teleportSound; public AudioClip pointerStartSound; public AudioClip pointerLoopSound; public AudioClip pointerStopSound; public AudioClip goodHighlightSound; public AudioClip badHighlightSound;
[Header( "Debug" )] public bool debugFloor = false; public bool showOffsetReticle = false; public Transform offsetReticleTransform; public MeshRenderer floorDebugSphere; public LineRenderer floorDebugLine;
private LineRenderer pointerLineRenderer; private GameObject teleportPointerObject; private Transform pointerStartTransform; private Hand pointerHand = null; private Player player = null; private TeleportArc teleportArc = null;
private bool visible = false;
private TeleportMarkerBase[] teleportMarkers; private TeleportMarkerBase pointedAtTeleportMarker; private TeleportMarkerBase teleportingToMarker; private Vector3 pointedAtPosition; private Vector3 prevPointedAtPosition; private bool teleporting = false; private float currentFadeTime = 0.0f;
private float meshAlphaPercent = 1.0f; private float pointerShowStartTime = 0.0f; private float pointerHideStartTime = 0.0f; private bool meshFading = false; private float fullTintAlpha;
private float invalidReticleMinScale = 0.2f; private float invalidReticleMaxScale = 1.0f; private float invalidReticleMinScaleDistance = 0.4f; private float invalidReticleMaxScaleDistance = 2.0f; private Vector3 invalidReticleScale = Vector3.one; private Quaternion invalidReticleTargetRotation = Quaternion.identity;
private Transform playAreaPreviewTransform; private Transform[] playAreaPreviewCorners; private Transform[] playAreaPreviewSides;
private float loopingAudioMaxVolume = 0.0f;
private Coroutine hintCoroutine = null;
private bool originalHoverLockState = false; private Interactable originalHoveringInteractable = null; private AllowTeleportWhileAttachedToHand allowTeleportWhileAttached = null;
private Vector3 startingFeetOffset = Vector3.zero; private bool movedFeetFarEnough = false;
SteamVR_Events.Action chaperoneInfoInitializedAction;
// Events
public static SteamVR_Events.Event< float > ChangeScene = new SteamVR_Events.Event< float >(); public static SteamVR_Events.Action< float > ChangeSceneAction( UnityAction< float > action ) { return new SteamVR_Events.Action< float >( ChangeScene, action ); }
public static SteamVR_Events.Event< TeleportMarkerBase > Player = new SteamVR_Events.Event< TeleportMarkerBase >(); public static SteamVR_Events.Action< TeleportMarkerBase > PlayerAction( UnityAction< TeleportMarkerBase > action ) { return new SteamVR_Events.Action< TeleportMarkerBase >( Player, action ); }
public static SteamVR_Events.Event< TeleportMarkerBase > PlayerPre = new SteamVR_Events.Event< TeleportMarkerBase >(); public static SteamVR_Events.Action< TeleportMarkerBase > PlayerPreAction( UnityAction< TeleportMarkerBase > action ) { return new SteamVR_Events.Action< TeleportMarkerBase >( PlayerPre, action ); }
//-------------------------------------------------
private static Teleport _instance; public static Teleport instance { get { if ( _instance == null ) { _instance = GameObject.FindObjectOfType<Teleport>(); }
return _instance; } }
//-------------------------------------------------
void Awake() { _instance = this;
chaperoneInfoInitializedAction = ChaperoneInfo.InitializedAction( OnChaperoneInfoInitialized );
pointerLineRenderer = GetComponentInChildren<LineRenderer>(); teleportPointerObject = pointerLineRenderer.gameObject;
#if UNITY_URP
fullTintAlpha = 0.5f;#else
int tintColorID = Shader.PropertyToID("_TintColor"); fullTintAlpha = pointVisibleMaterial.GetColor(tintColorID).a;#endif
teleportArc = GetComponent<TeleportArc>(); teleportArc.traceLayerMask = traceLayerMask;
loopingAudioMaxVolume = loopingAudioSource.volume;
playAreaPreviewCorner.SetActive( false ); playAreaPreviewSide.SetActive( false );
float invalidReticleStartingScale = invalidReticleTransform.localScale.x; invalidReticleMinScale *= invalidReticleStartingScale; invalidReticleMaxScale *= invalidReticleStartingScale; }
//-------------------------------------------------
void Start() { teleportMarkers = GameObject.FindObjectsOfType<TeleportMarkerBase>();
HidePointer();
player = InteractionSystem.Player.instance;
if ( player == null ) { Debug.LogError("<b>[SteamVR Interaction]</b> Teleport: No Player instance found in map.", this); Destroy( this.gameObject ); return; }
CheckForSpawnPoint();
Invoke( "ShowTeleportHint", 5.0f ); }
//-------------------------------------------------
void OnEnable() { chaperoneInfoInitializedAction.enabled = true; OnChaperoneInfoInitialized(); // In case it's already initialized
}
//-------------------------------------------------
void OnDisable() { chaperoneInfoInitializedAction.enabled = false; HidePointer(); }
//-------------------------------------------------
private void CheckForSpawnPoint() { foreach ( TeleportMarkerBase teleportMarker in teleportMarkers ) { TeleportPoint teleportPoint = teleportMarker as TeleportPoint; if ( teleportPoint && teleportPoint.playerSpawnPoint ) { teleportingToMarker = teleportMarker; TeleportPlayer(); break; } } }
//-------------------------------------------------
public void HideTeleportPointer() { if ( pointerHand != null ) { HidePointer(); } }
//-------------------------------------------------
void Update() { Hand oldPointerHand = pointerHand; Hand newPointerHand = null;
foreach ( Hand hand in player.hands ) { if ( visible ) { if ( WasTeleportButtonReleased( hand ) ) { if ( pointerHand == hand ) //This is the pointer hand
{ TryTeleportPlayer(); } } }
if ( WasTeleportButtonPressed( hand ) ) { newPointerHand = hand; } }
//If something is attached to the hand that is preventing teleport
if ( allowTeleportWhileAttached && !allowTeleportWhileAttached.teleportAllowed ) { HidePointer(); } else { if ( !visible && newPointerHand != null ) { //Begin showing the pointer
ShowPointer( newPointerHand, oldPointerHand ); } else if ( visible ) { if ( newPointerHand == null && !IsTeleportButtonDown( pointerHand ) ) { //Hide the pointer
HidePointer(); } else if ( newPointerHand != null ) { //Move the pointer to a new hand
ShowPointer( newPointerHand, oldPointerHand ); } } }
if ( visible ) { UpdatePointer();
if ( meshFading ) { UpdateTeleportColors(); }
if ( onActivateObjectTransform.gameObject.activeSelf && Time.time - pointerShowStartTime > activateObjectTime ) { onActivateObjectTransform.gameObject.SetActive( false ); } } else { if ( onDeactivateObjectTransform.gameObject.activeSelf && Time.time - pointerHideStartTime > deactivateObjectTime ) { onDeactivateObjectTransform.gameObject.SetActive( false ); } } }
//-------------------------------------------------
private void UpdatePointer() { Vector3 pointerStart = pointerStartTransform.position; Vector3 pointerEnd; Vector3 pointerDir = pointerStartTransform.forward; bool hitSomething = false; bool showPlayAreaPreview = false; Vector3 playerFeetOffset = player.trackingOriginTransform.position - player.feetPositionGuess;
Vector3 arcVelocity = pointerDir * arcDistance;
TeleportMarkerBase hitTeleportMarker = null;
//Check pointer angle
float dotUp = Vector3.Dot( pointerDir, Vector3.up ); float dotForward = Vector3.Dot( pointerDir, player.hmdTransform.forward ); bool pointerAtBadAngle = false; if ( ( dotForward > 0 && dotUp > 0.75f ) || ( dotForward < 0.0f && dotUp > 0.5f ) ) { pointerAtBadAngle = true; }
//Trace to see if the pointer hit anything
RaycastHit hitInfo; teleportArc.SetArcData( pointerStart, arcVelocity, true, pointerAtBadAngle ); if ( teleportArc.DrawArc( out hitInfo ) ) { hitSomething = true; hitTeleportMarker = hitInfo.collider.GetComponentInParent<TeleportMarkerBase>(); }
if ( pointerAtBadAngle ) { hitTeleportMarker = null; }
HighlightSelected( hitTeleportMarker );
if ( hitTeleportMarker != null ) //Hit a teleport marker
{ if ( hitTeleportMarker.locked ) { teleportArc.SetColor( pointerLockedColor );#if (UNITY_5_4)
pointerLineRenderer.SetColors( pointerLockedColor, pointerLockedColor );#else
pointerLineRenderer.startColor = pointerLockedColor; pointerLineRenderer.endColor = pointerLockedColor;#endif
destinationReticleTransform.gameObject.SetActive( false ); } else { teleportArc.SetColor( pointerValidColor );#if (UNITY_5_4)
pointerLineRenderer.SetColors( pointerValidColor, pointerValidColor );#else
pointerLineRenderer.startColor = pointerValidColor; pointerLineRenderer.endColor = pointerValidColor;#endif
destinationReticleTransform.gameObject.SetActive( hitTeleportMarker.showReticle ); }
offsetReticleTransform.gameObject.SetActive( true );
invalidReticleTransform.gameObject.SetActive( false );
pointedAtTeleportMarker = hitTeleportMarker; pointedAtPosition = hitInfo.point;
if ( showPlayAreaMarker ) { //Show the play area marker if this is a teleport area
TeleportArea teleportArea = pointedAtTeleportMarker as TeleportArea; if ( teleportArea != null && !teleportArea.locked && playAreaPreviewTransform != null ) { Vector3 offsetToUse = playerFeetOffset;
//Adjust the actual offset to prevent the play area marker from moving too much
if ( !movedFeetFarEnough ) { float distanceFromStartingOffset = Vector3.Distance( playerFeetOffset, startingFeetOffset ); if ( distanceFromStartingOffset < 0.1f ) { offsetToUse = startingFeetOffset; } else if ( distanceFromStartingOffset < 0.4f ) { offsetToUse = Vector3.Lerp( startingFeetOffset, playerFeetOffset, ( distanceFromStartingOffset - 0.1f ) / 0.3f ); } else { movedFeetFarEnough = true; } }
playAreaPreviewTransform.position = pointedAtPosition + offsetToUse;
showPlayAreaPreview = true; } }
pointerEnd = hitInfo.point; } else //Hit neither
{ destinationReticleTransform.gameObject.SetActive( false ); offsetReticleTransform.gameObject.SetActive( false );
teleportArc.SetColor( pointerInvalidColor );#if (UNITY_5_4)
pointerLineRenderer.SetColors( pointerInvalidColor, pointerInvalidColor );#else
pointerLineRenderer.startColor = pointerInvalidColor; pointerLineRenderer.endColor = pointerInvalidColor;#endif
invalidReticleTransform.gameObject.SetActive( !pointerAtBadAngle );
//Orient the invalid reticle to the normal of the trace hit point
Vector3 normalToUse = hitInfo.normal; float angle = Vector3.Angle( hitInfo.normal, Vector3.up ); if ( angle < 15.0f ) { normalToUse = Vector3.up; } invalidReticleTargetRotation = Quaternion.FromToRotation( Vector3.up, normalToUse ); invalidReticleTransform.rotation = Quaternion.Slerp( invalidReticleTransform.rotation, invalidReticleTargetRotation, 0.1f );
//Scale the invalid reticle based on the distance from the player
float distanceFromPlayer = Vector3.Distance( hitInfo.point, player.hmdTransform.position ); float invalidReticleCurrentScale = Util.RemapNumberClamped( distanceFromPlayer, invalidReticleMinScaleDistance, invalidReticleMaxScaleDistance, invalidReticleMinScale, invalidReticleMaxScale ); invalidReticleScale.x = invalidReticleCurrentScale; invalidReticleScale.y = invalidReticleCurrentScale; invalidReticleScale.z = invalidReticleCurrentScale; invalidReticleTransform.transform.localScale = invalidReticleScale;
pointedAtTeleportMarker = null;
if ( hitSomething ) { pointerEnd = hitInfo.point; } else { pointerEnd = teleportArc.GetArcPositionAtTime( teleportArc.arcDuration ); }
//Debug floor
if ( debugFloor ) { floorDebugSphere.gameObject.SetActive( false ); floorDebugLine.gameObject.SetActive( false ); } }
if ( playAreaPreviewTransform != null ) { playAreaPreviewTransform.gameObject.SetActive( showPlayAreaPreview ); }
if ( !showOffsetReticle ) { offsetReticleTransform.gameObject.SetActive( false ); }
destinationReticleTransform.position = pointedAtPosition; invalidReticleTransform.position = pointerEnd; onActivateObjectTransform.position = pointerEnd; onDeactivateObjectTransform.position = pointerEnd; offsetReticleTransform.position = pointerEnd - playerFeetOffset;
reticleAudioSource.transform.position = pointedAtPosition;
pointerLineRenderer.SetPosition( 0, pointerStart ); pointerLineRenderer.SetPosition( 1, pointerEnd ); }
//-------------------------------------------------
void FixedUpdate() { if ( !visible ) { return; }
if ( debugFloor ) { //Debug floor
TeleportArea teleportArea = pointedAtTeleportMarker as TeleportArea; if ( teleportArea != null ) { if ( floorFixupMaximumTraceDistance > 0.0f ) { floorDebugSphere.gameObject.SetActive( true ); floorDebugLine.gameObject.SetActive( true );
RaycastHit raycastHit; Vector3 traceDir = Vector3.down; traceDir.x = 0.01f; if ( Physics.Raycast( pointedAtPosition + 0.05f * traceDir, traceDir, out raycastHit, floorFixupMaximumTraceDistance, floorFixupTraceLayerMask ) ) { floorDebugSphere.transform.position = raycastHit.point; floorDebugSphere.material.color = Color.green;#if (UNITY_5_4)
floorDebugLine.SetColors( Color.green, Color.green );#else
floorDebugLine.startColor = Color.green; floorDebugLine.endColor = Color.green;#endif
floorDebugLine.SetPosition( 0, pointedAtPosition ); floorDebugLine.SetPosition( 1, raycastHit.point ); } else { Vector3 rayEnd = pointedAtPosition + ( traceDir * floorFixupMaximumTraceDistance ); floorDebugSphere.transform.position = rayEnd; floorDebugSphere.material.color = Color.red;#if (UNITY_5_4)
floorDebugLine.SetColors( Color.red, Color.red );#else
floorDebugLine.startColor = Color.red; floorDebugLine.endColor = Color.red;#endif
floorDebugLine.SetPosition( 0, pointedAtPosition ); floorDebugLine.SetPosition( 1, rayEnd ); } } } } }
//-------------------------------------------------
private void OnChaperoneInfoInitialized() { ChaperoneInfo chaperone = ChaperoneInfo.instance;
if ( chaperone.initialized && chaperone.roomscale ) { //Set up the render model for the play area bounds
if ( playAreaPreviewTransform == null ) { playAreaPreviewTransform = new GameObject( "PlayAreaPreviewTransform" ).transform; playAreaPreviewTransform.parent = transform; Util.ResetTransform( playAreaPreviewTransform );
playAreaPreviewCorner.SetActive( true ); playAreaPreviewCorners = new Transform[4]; playAreaPreviewCorners[0] = playAreaPreviewCorner.transform; playAreaPreviewCorners[1] = Instantiate( playAreaPreviewCorners[0] ); playAreaPreviewCorners[2] = Instantiate( playAreaPreviewCorners[0] ); playAreaPreviewCorners[3] = Instantiate( playAreaPreviewCorners[0] );
playAreaPreviewCorners[0].transform.parent = playAreaPreviewTransform; playAreaPreviewCorners[1].transform.parent = playAreaPreviewTransform; playAreaPreviewCorners[2].transform.parent = playAreaPreviewTransform; playAreaPreviewCorners[3].transform.parent = playAreaPreviewTransform;
playAreaPreviewSide.SetActive( true ); playAreaPreviewSides = new Transform[4]; playAreaPreviewSides[0] = playAreaPreviewSide.transform; playAreaPreviewSides[1] = Instantiate( playAreaPreviewSides[0] ); playAreaPreviewSides[2] = Instantiate( playAreaPreviewSides[0] ); playAreaPreviewSides[3] = Instantiate( playAreaPreviewSides[0] );
playAreaPreviewSides[0].transform.parent = playAreaPreviewTransform; playAreaPreviewSides[1].transform.parent = playAreaPreviewTransform; playAreaPreviewSides[2].transform.parent = playAreaPreviewTransform; playAreaPreviewSides[3].transform.parent = playAreaPreviewTransform; }
float x = chaperone.playAreaSizeX; float z = chaperone.playAreaSizeZ;
playAreaPreviewSides[0].localPosition = new Vector3( 0.0f, 0.0f, 0.5f * z - 0.25f ); playAreaPreviewSides[1].localPosition = new Vector3( 0.0f, 0.0f, -0.5f * z + 0.25f ); playAreaPreviewSides[2].localPosition = new Vector3( 0.5f * x - 0.25f, 0.0f, 0.0f ); playAreaPreviewSides[3].localPosition = new Vector3( -0.5f * x + 0.25f, 0.0f, 0.0f );
playAreaPreviewSides[0].localScale = new Vector3( x - 0.5f, 1.0f, 1.0f ); playAreaPreviewSides[1].localScale = new Vector3( x - 0.5f, 1.0f, 1.0f ); playAreaPreviewSides[2].localScale = new Vector3( z - 0.5f, 1.0f, 1.0f ); playAreaPreviewSides[3].localScale = new Vector3( z - 0.5f, 1.0f, 1.0f );
playAreaPreviewSides[0].localRotation = Quaternion.Euler( 0.0f, 0.0f, 0.0f ); playAreaPreviewSides[1].localRotation = Quaternion.Euler( 0.0f, 180.0f, 0.0f ); playAreaPreviewSides[2].localRotation = Quaternion.Euler( 0.0f, 90.0f, 0.0f ); playAreaPreviewSides[3].localRotation = Quaternion.Euler( 0.0f, 270.0f, 0.0f );
playAreaPreviewCorners[0].localPosition = new Vector3( 0.5f * x - 0.25f, 0.0f, 0.5f * z - 0.25f ); playAreaPreviewCorners[1].localPosition = new Vector3( 0.5f * x - 0.25f, 0.0f, -0.5f * z + 0.25f ); playAreaPreviewCorners[2].localPosition = new Vector3( -0.5f * x + 0.25f, 0.0f, -0.5f * z + 0.25f ); playAreaPreviewCorners[3].localPosition = new Vector3( -0.5f * x + 0.25f, 0.0f, 0.5f * z - 0.25f );
playAreaPreviewCorners[0].localRotation = Quaternion.Euler( 0.0f, 0.0f, 0.0f ); playAreaPreviewCorners[1].localRotation = Quaternion.Euler( 0.0f, 90.0f, 0.0f ); playAreaPreviewCorners[2].localRotation = Quaternion.Euler( 0.0f, 180.0f, 0.0f ); playAreaPreviewCorners[3].localRotation = Quaternion.Euler( 0.0f, 270.0f, 0.0f );
playAreaPreviewTransform.gameObject.SetActive( false ); } }
//-------------------------------------------------
private void HidePointer() { if ( visible ) { pointerHideStartTime = Time.time; }
visible = false; if ( pointerHand ) { if ( ShouldOverrideHoverLock() ) { //Restore the original hovering interactable on the hand
if ( originalHoverLockState == true ) { pointerHand.HoverLock( originalHoveringInteractable ); } else { pointerHand.HoverUnlock( null ); } }
//Stop looping sound
loopingAudioSource.Stop(); PlayAudioClip( pointerAudioSource, pointerStopSound ); } teleportPointerObject.SetActive( false );
teleportArc.Hide();
foreach ( TeleportMarkerBase teleportMarker in teleportMarkers ) { if ( teleportMarker != null && teleportMarker.markerActive && teleportMarker.gameObject != null ) { teleportMarker.gameObject.SetActive( false ); } }
destinationReticleTransform.gameObject.SetActive( false ); invalidReticleTransform.gameObject.SetActive( false ); offsetReticleTransform.gameObject.SetActive( false );
if ( playAreaPreviewTransform != null ) { playAreaPreviewTransform.gameObject.SetActive( false ); }
if ( onActivateObjectTransform.gameObject.activeSelf ) { onActivateObjectTransform.gameObject.SetActive( false ); } onDeactivateObjectTransform.gameObject.SetActive( true );
pointerHand = null; }
//-------------------------------------------------
private void ShowPointer( Hand newPointerHand, Hand oldPointerHand ) { if ( !visible ) { pointedAtTeleportMarker = null; pointerShowStartTime = Time.time; visible = true; meshFading = true;
teleportPointerObject.SetActive( false ); teleportArc.Show();
foreach ( TeleportMarkerBase teleportMarker in teleportMarkers ) { if ( teleportMarker.markerActive && teleportMarker.ShouldActivate( player.feetPositionGuess ) ) { teleportMarker.gameObject.SetActive( true ); teleportMarker.Highlight( false ); } }
startingFeetOffset = player.trackingOriginTransform.position - player.feetPositionGuess; movedFeetFarEnough = false;
if ( onDeactivateObjectTransform.gameObject.activeSelf ) { onDeactivateObjectTransform.gameObject.SetActive( false ); } onActivateObjectTransform.gameObject.SetActive( true );
loopingAudioSource.clip = pointerLoopSound; loopingAudioSource.loop = true; loopingAudioSource.Play(); loopingAudioSource.volume = 0.0f; }
if ( oldPointerHand ) { if ( ShouldOverrideHoverLock() ) { //Restore the original hovering interactable on the hand
if ( originalHoverLockState == true ) { oldPointerHand.HoverLock( originalHoveringInteractable ); } else { oldPointerHand.HoverUnlock( null ); } } }
pointerHand = newPointerHand;
if ( visible && oldPointerHand != pointerHand ) { PlayAudioClip( pointerAudioSource, pointerStartSound ); }
if ( pointerHand ) { pointerStartTransform = GetPointerStartTransform( pointerHand );
if ( pointerHand.currentAttachedObject != null ) { allowTeleportWhileAttached = pointerHand.currentAttachedObject.GetComponent<AllowTeleportWhileAttachedToHand>(); }
//Keep track of any existing hovering interactable on the hand
originalHoverLockState = pointerHand.hoverLocked; originalHoveringInteractable = pointerHand.hoveringInteractable;
if ( ShouldOverrideHoverLock() ) { pointerHand.HoverLock( null ); }
pointerAudioSource.transform.SetParent( pointerStartTransform ); pointerAudioSource.transform.localPosition = Vector3.zero;
loopingAudioSource.transform.SetParent( pointerStartTransform ); loopingAudioSource.transform.localPosition = Vector3.zero; } }
//-------------------------------------------------
private void UpdateTeleportColors() { float deltaTime = Time.time - pointerShowStartTime; if ( deltaTime > meshFadeTime ) { meshAlphaPercent = 1.0f; meshFading = false; } else { meshAlphaPercent = Mathf.Lerp( 0.0f, 1.0f, deltaTime / meshFadeTime ); }
//Tint color for the teleport points
foreach ( TeleportMarkerBase teleportMarker in teleportMarkers ) { teleportMarker.SetAlpha( fullTintAlpha * meshAlphaPercent, meshAlphaPercent ); } }
//-------------------------------------------------
private void PlayAudioClip( AudioSource source, AudioClip clip ) { source.clip = clip; source.Play(); }
//-------------------------------------------------
private void PlayPointerHaptic( bool validLocation ) { if ( pointerHand != null ) { if ( validLocation ) { pointerHand.TriggerHapticPulse( 800 ); } else { pointerHand.TriggerHapticPulse( 100 ); } } }
//-------------------------------------------------
private void TryTeleportPlayer() { if ( visible && !teleporting ) { if ( pointedAtTeleportMarker != null && pointedAtTeleportMarker.locked == false ) { //Pointing at an unlocked teleport marker
teleportingToMarker = pointedAtTeleportMarker; InitiateTeleportFade();
CancelTeleportHint(); } } }
//-------------------------------------------------
private void InitiateTeleportFade() { teleporting = true;
currentFadeTime = teleportFadeTime;
TeleportPoint teleportPoint = teleportingToMarker as TeleportPoint; if ( teleportPoint != null && teleportPoint.teleportType == TeleportPoint.TeleportPointType.SwitchToNewScene ) { currentFadeTime *= 3.0f; Teleport.ChangeScene.Send( currentFadeTime ); }
SteamVR_Fade.Start( Color.clear, 0 ); SteamVR_Fade.Start( Color.black, currentFadeTime );
headAudioSource.transform.SetParent( player.hmdTransform ); headAudioSource.transform.localPosition = Vector3.zero; PlayAudioClip( headAudioSource, teleportSound );
Invoke( "TeleportPlayer", currentFadeTime ); }
//-------------------------------------------------
private void TeleportPlayer() { teleporting = false;
Teleport.PlayerPre.Send( pointedAtTeleportMarker );
SteamVR_Fade.Start( Color.clear, currentFadeTime );
TeleportPoint teleportPoint = teleportingToMarker as TeleportPoint; Vector3 teleportPosition = pointedAtPosition;
if ( teleportPoint != null ) { teleportPosition = teleportPoint.transform.position;
//Teleport to a new scene
if ( teleportPoint.teleportType == TeleportPoint.TeleportPointType.SwitchToNewScene ) { teleportPoint.TeleportToScene(); return; } }
// Find the actual floor position below the navigation mesh
TeleportArea teleportArea = teleportingToMarker as TeleportArea; if ( teleportArea != null ) { if ( floorFixupMaximumTraceDistance > 0.0f ) { RaycastHit raycastHit; if ( Physics.Raycast( teleportPosition + 0.05f * Vector3.down, Vector3.down, out raycastHit, floorFixupMaximumTraceDistance, floorFixupTraceLayerMask ) ) { teleportPosition = raycastHit.point; } } }
if ( teleportingToMarker.ShouldMovePlayer() ) { Vector3 playerFeetOffset = player.trackingOriginTransform.position - player.feetPositionGuess; player.trackingOriginTransform.position = teleportPosition + playerFeetOffset;
if (player.leftHand.currentAttachedObjectInfo.HasValue) player.leftHand.ResetAttachedTransform(player.leftHand.currentAttachedObjectInfo.Value); if (player.rightHand.currentAttachedObjectInfo.HasValue) player.rightHand.ResetAttachedTransform(player.rightHand.currentAttachedObjectInfo.Value); } else { teleportingToMarker.TeleportPlayer( pointedAtPosition ); }
Teleport.Player.Send( pointedAtTeleportMarker ); }
//-------------------------------------------------
private void HighlightSelected( TeleportMarkerBase hitTeleportMarker ) { if ( pointedAtTeleportMarker != hitTeleportMarker ) //Pointing at a new teleport marker
{ if ( pointedAtTeleportMarker != null ) { pointedAtTeleportMarker.Highlight( false ); }
if ( hitTeleportMarker != null ) { hitTeleportMarker.Highlight( true );
prevPointedAtPosition = pointedAtPosition; PlayPointerHaptic( !hitTeleportMarker.locked );
PlayAudioClip( reticleAudioSource, goodHighlightSound );
loopingAudioSource.volume = loopingAudioMaxVolume; } else if ( pointedAtTeleportMarker != null ) { PlayAudioClip( reticleAudioSource, badHighlightSound );
loopingAudioSource.volume = 0.0f; } } else if ( hitTeleportMarker != null ) //Pointing at the same teleport marker
{ if ( Vector3.Distance( prevPointedAtPosition, pointedAtPosition ) > 1.0f ) { prevPointedAtPosition = pointedAtPosition; PlayPointerHaptic( !hitTeleportMarker.locked ); } } }
//-------------------------------------------------
public void ShowTeleportHint() { CancelTeleportHint();
hintCoroutine = StartCoroutine( TeleportHintCoroutine() ); }
//-------------------------------------------------
public void CancelTeleportHint() { if ( hintCoroutine != null ) { ControllerButtonHints.HideTextHint(player.leftHand, teleportAction); ControllerButtonHints.HideTextHint(player.rightHand, teleportAction);
StopCoroutine( hintCoroutine ); hintCoroutine = null; }
CancelInvoke( "ShowTeleportHint" ); }
//-------------------------------------------------
private IEnumerator TeleportHintCoroutine() { float prevBreakTime = Time.time; float prevHapticPulseTime = Time.time;
while ( true ) { bool pulsed = false;
//Show the hint on each eligible hand
foreach ( Hand hand in player.hands ) { bool showHint = IsEligibleForTeleport( hand ); bool isShowingHint = !string.IsNullOrEmpty( ControllerButtonHints.GetActiveHintText( hand, teleportAction) ); if ( showHint ) { if ( !isShowingHint ) { ControllerButtonHints.ShowTextHint( hand, teleportAction, "Teleport" ); prevBreakTime = Time.time; prevHapticPulseTime = Time.time; }
if ( Time.time > prevHapticPulseTime + 0.05f ) { //Haptic pulse for a few seconds
pulsed = true;
hand.TriggerHapticPulse( 500 ); } } else if ( !showHint && isShowingHint ) { ControllerButtonHints.HideTextHint( hand, teleportAction); } }
if ( Time.time > prevBreakTime + 3.0f ) { //Take a break for a few seconds
yield return new WaitForSeconds( 3.0f );
prevBreakTime = Time.time; }
if ( pulsed ) { prevHapticPulseTime = Time.time; }
yield return null; } }
//-------------------------------------------------
public bool IsEligibleForTeleport( Hand hand ) { if ( hand == null ) { return false; }
if ( !hand.gameObject.activeInHierarchy ) { return false; }
if ( hand.hoveringInteractable != null ) { return false; }
if ( hand.noSteamVRFallbackCamera == null ) { if ( hand.isActive == false) { return false; }
//Something is attached to the hand
if ( hand.currentAttachedObject != null ) { AllowTeleportWhileAttachedToHand allowTeleportWhileAttachedToHand = hand.currentAttachedObject.GetComponent<AllowTeleportWhileAttachedToHand>();
if ( allowTeleportWhileAttachedToHand != null && allowTeleportWhileAttachedToHand.teleportAllowed == true ) { return true; } else { return false; } } }
return true; }
//-------------------------------------------------
private bool ShouldOverrideHoverLock() { if ( !allowTeleportWhileAttached || allowTeleportWhileAttached.overrideHoverLock ) { return true; }
return false; }
//-------------------------------------------------
private bool WasTeleportButtonReleased( Hand hand ) { if ( IsEligibleForTeleport( hand ) ) { if ( hand.noSteamVRFallbackCamera != null ) { return Input.GetKeyUp( KeyCode.T ); } else { return teleportAction.GetStateUp(hand.handType);
//return hand.controller.GetPressUp( SteamVR_Controller.ButtonMask.Touchpad );
} }
return false; }
//-------------------------------------------------
private bool IsTeleportButtonDown( Hand hand ) { if ( IsEligibleForTeleport( hand ) ) { if ( hand.noSteamVRFallbackCamera != null ) { return Input.GetKey( KeyCode.T ); } else { return teleportAction.GetState(hand.handType); } }
return false; }
//-------------------------------------------------
private bool WasTeleportButtonPressed( Hand hand ) { if ( IsEligibleForTeleport( hand ) ) { if ( hand.noSteamVRFallbackCamera != null ) { return Input.GetKeyDown( KeyCode.T ); } else { return teleportAction.GetStateDown(hand.handType);
//return hand.controller.GetPressDown( SteamVR_Controller.ButtonMask.Touchpad );
} }
return false; }
//-------------------------------------------------
private Transform GetPointerStartTransform( Hand hand ) { if ( hand.noSteamVRFallbackCamera != null ) { return hand.noSteamVRFallbackCamera.transform; } else { return hand.transform; } } }}
|