using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using Unity.XR.CoreUtils; using UnityEngine; using UnityEngine.XR; using UnityEngine.XR.Interaction.Toolkit; public class StencilPortal : MonoBehaviour { public bool destroyAfterTeleport; public StencilPortal targetPortal; public Transform normalVisible; public Transform normalInvisible; public LayerMask defaultLayer; public LayerMask portalLayer; public PortalScene portalScene; public OcclusionPortal occlusionPortal; public bool _shouldTeleport; public TeleportationProvider teleportationProvider; // Reference to TeleportationProvider public static Vector3 TransformPositionBetweenPortals(StencilPortal sender, StencilPortal target, Vector3 position) { return target.normalInvisible.TransformPoint(sender.normalVisible.InverseTransformPoint(position)); } public static Quaternion TransformRotationBetweenPortals(StencilPortal sender, StencilPortal target, Quaternion rotation) { return target.normalInvisible.rotation * Quaternion.Inverse(sender.normalVisible.rotation) * rotation; } private void OnTriggerEnter(Collider other) { if (other.GetComponent() == null) return; if (occlusionPortal != null) { occlusionPortal.open = !occlusionPortal.open; } if (!_shouldTeleport) { if (destroyAfterTeleport) { Destroy(gameObject, 0.5f); } return; } Debug.Log(transform.name + " player entered and should teleport"); targetPortal._shouldTeleport = false; if (teleportationProvider != null) { Vector3 targetPosition = TransformPositionBetweenPortals(this, targetPortal, other.transform.position); Quaternion targetRotation = TransformRotationBetweenPortals(this, targetPortal, other.transform.rotation); TeleportRequest request = new TeleportRequest { destinationPosition = targetPosition, destinationRotation = targetRotation, matchOrientation = MatchOrientation.TargetUpAndForward }; teleportationProvider.QueueTeleportRequest(request); other.transform.rotation = TransformRotationBetweenPortals(this, targetPortal, other.transform.rotation); } else { Debug.LogWarning("TeleportationProvider is not assigned!", this); other.transform.position = TransformPositionBetweenPortals(this, targetPortal, other.transform.position); other.transform.rotation = TransformRotationBetweenPortals(this, targetPortal, other.transform.rotation); } if (destroyAfterTeleport) { Destroy(gameObject, 0.5f); } } private void OnTriggerExit(Collider other) { AllowTeleport(); if (!_shouldTeleport || IsInvoking(nameof(AllowTeleport))) return; if (!other.CompareTag("Player")) return; Debug.Log(transform.name + " player exited"); Invoke(nameof(AllowTeleport), 1f); } private void AllowTeleport() { _shouldTeleport = true; } public StencilPortal TargetPortal => targetPortal; public LayerMask DefaultLayer => defaultLayer; public LayerMask PortalLayer => portalLayer; }