You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
5.7 KiB
143 lines
5.7 KiB
using UnityEngine.XR.Interaction.Toolkit.Locomotion.Climbing; |
|
using UnityEngine.XR.Interaction.Toolkit.Locomotion.Teleportation; |
|
using UnityEngine.XR.Interaction.Toolkit.Utilities; |
|
|
|
namespace UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets |
|
{ |
|
/// <summary> |
|
/// Affordance component used in conjunction with a <see cref="ClimbTeleportInteractor"/> to display an object |
|
/// pointing at the target teleport destination while climbing. |
|
/// </summary> |
|
public class ClimbTeleportDestinationIndicator : MonoBehaviour |
|
{ |
|
[SerializeField] |
|
[Tooltip("The interactor that drives the display and placement of the pointer object.")] |
|
ClimbTeleportInteractor m_ClimbTeleportInteractor; |
|
|
|
/// <summary> |
|
/// The interactor that drives the display and placement of the pointer object. |
|
/// </summary> |
|
public ClimbTeleportInteractor climbTeleportInteractor |
|
{ |
|
get => m_ClimbTeleportInteractor; |
|
set => m_ClimbTeleportInteractor = value; |
|
} |
|
|
|
[SerializeField] |
|
[Tooltip("The prefab to spawn when a teleport destination is chosen. The instance will spawn next to the " + |
|
"destination and point its forward vector at the destination and its up vector at the camera.")] |
|
GameObject m_PointerPrefab; |
|
|
|
/// <summary> |
|
/// The prefab to spawn when a teleport destination is chosen. The instance will spawn next to the destination |
|
/// and point its forward vector at the destination and its up vector at the camera. |
|
/// </summary> |
|
public GameObject pointerPrefab |
|
{ |
|
get => m_PointerPrefab; |
|
set => m_PointerPrefab = value; |
|
} |
|
|
|
[SerializeField] |
|
[Tooltip("The distance from the destination at which the pointer object spawns.")] |
|
float m_PointerDistance = 0.3f; |
|
|
|
/// <summary> |
|
/// The distance from the destination at which the pointer object spawns. |
|
/// </summary> |
|
public float pointerDistance |
|
{ |
|
get => m_PointerDistance; |
|
set => m_PointerDistance = value; |
|
} |
|
|
|
TeleportationMultiAnchorVolume m_ActiveTeleportVolume; |
|
Transform m_PointerInstance; |
|
|
|
/// <summary> |
|
/// See <see cref="MonoBehaviour"/>. |
|
/// </summary> |
|
protected void OnEnable() |
|
{ |
|
if (m_ClimbTeleportInteractor == null) |
|
{ |
|
if (!ComponentLocatorUtility<ClimbTeleportInteractor>.TryFindComponent(out m_ClimbTeleportInteractor)) |
|
{ |
|
Debug.LogError($"Could not find {nameof(ClimbTeleportInteractor)} in scene."); |
|
enabled = false; |
|
return; |
|
} |
|
} |
|
|
|
m_ClimbTeleportInteractor.hoverEntered.AddListener(OnInteractorHoverEntered); |
|
m_ClimbTeleportInteractor.hoverExited.AddListener(OnInteractorHoverExited); |
|
} |
|
|
|
/// <summary> |
|
/// See <see cref="MonoBehaviour"/>. |
|
/// </summary> |
|
protected void OnDisable() |
|
{ |
|
HideIndicator(); |
|
|
|
if (m_ActiveTeleportVolume != null) |
|
{ |
|
m_ActiveTeleportVolume.destinationAnchorChanged -= OnClimbTeleportDestinationAnchorChanged; |
|
m_ActiveTeleportVolume = null; |
|
} |
|
|
|
if (m_ClimbTeleportInteractor != null) |
|
{ |
|
m_ClimbTeleportInteractor.hoverEntered.RemoveListener(OnInteractorHoverEntered); |
|
m_ClimbTeleportInteractor.hoverExited.RemoveListener(OnInteractorHoverExited); |
|
} |
|
} |
|
|
|
void OnInteractorHoverEntered(HoverEnterEventArgs args) |
|
{ |
|
if (m_ActiveTeleportVolume != null || !(args.interactableObject is TeleportationMultiAnchorVolume teleportVolume)) |
|
return; |
|
|
|
m_ActiveTeleportVolume = teleportVolume; |
|
if (m_ActiveTeleportVolume.destinationAnchor != null) |
|
OnClimbTeleportDestinationAnchorChanged(m_ActiveTeleportVolume); |
|
|
|
m_ActiveTeleportVolume.destinationAnchorChanged += OnClimbTeleportDestinationAnchorChanged; |
|
} |
|
|
|
void OnInteractorHoverExited(HoverExitEventArgs args) |
|
{ |
|
if (!(args.interactableObject is TeleportationMultiAnchorVolume teleportVolume) || teleportVolume != m_ActiveTeleportVolume) |
|
return; |
|
|
|
HideIndicator(); |
|
m_ActiveTeleportVolume.destinationAnchorChanged -= OnClimbTeleportDestinationAnchorChanged; |
|
m_ActiveTeleportVolume = null; |
|
} |
|
|
|
void OnClimbTeleportDestinationAnchorChanged(TeleportationMultiAnchorVolume teleportVolume) |
|
{ |
|
HideIndicator(); |
|
|
|
var destinationAnchor = teleportVolume.destinationAnchor; |
|
if (destinationAnchor == null) |
|
return; |
|
|
|
m_PointerInstance = Instantiate(m_PointerPrefab).transform; |
|
var cameraTrans = teleportVolume.teleportationProvider.system.xrOrigin.Camera.transform; |
|
var cameraPosition = cameraTrans.position; |
|
var destinationPosition = destinationAnchor.position; |
|
var destinationDirectionInScreenSpace = cameraTrans.InverseTransformDirection(destinationPosition - cameraPosition); |
|
destinationDirectionInScreenSpace.z = 0f; |
|
var pointerDirection = cameraTrans.TransformDirection(destinationDirectionInScreenSpace).normalized; |
|
m_PointerInstance.position = destinationPosition - pointerDirection * m_PointerDistance; |
|
m_PointerInstance.rotation = Quaternion.LookRotation(pointerDirection, -cameraTrans.forward); |
|
} |
|
|
|
void HideIndicator() |
|
{ |
|
if (m_PointerInstance != null) |
|
Destroy(m_PointerInstance.gameObject); |
|
} |
|
} |
|
}
|
|
|