104 lines
3.4 KiB
C#
104 lines
3.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using Unity.XR.CoreUtils;
|
|
using UnityEngine;
|
|
using UnityEngine.XR;
|
|
|
|
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 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)
|
|
{
|
|
//Debug.Log(transform.name + " player entered and should teleport");
|
|
if (other.GetComponent<XROrigin>() == 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;
|
|
|
|
// Move player to target portal collider relative position
|
|
other.transform.position = TransformPositionBetweenPortals(this, targetPortal, other.transform.position);
|
|
other.transform.rotation = TransformRotationBetweenPortals(this, targetPortal, other.transform.rotation);
|
|
//rotatePlayer(other,targetPortal);
|
|
if (destroyAfterTeleport)
|
|
{
|
|
Destroy(gameObject, 0.5f);
|
|
}
|
|
}
|
|
private void rotatePlayer(Collider collider, StencilPortal target)
|
|
{
|
|
XROrigin Player = collider.GetComponent<XROrigin>();
|
|
if (target != null && Player != null && Player.Camera != null)
|
|
{
|
|
// Calculate the rotation offset needed for the player
|
|
Vector3 targetEulerAngles = target.transform.rotation.eulerAngles;
|
|
Vector3 currentCameraEulerAngles = Player.Camera.transform.rotation.eulerAngles;
|
|
|
|
// Determine the rotation delta around the Y-axis
|
|
float rotationDeltaY = targetEulerAngles.y - currentCameraEulerAngles.y - 180;
|
|
|
|
// Apply the rotation delta to the XR Origin
|
|
Player.transform.Rotate(0, rotationDeltaY, 0, Space.World);
|
|
}
|
|
}
|
|
|
|
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;
|
|
} |