using System; using UnityEngine; namespace Escape_Room_Engine.Portal { [RequireComponent(typeof(Collider), typeof(Rigidbody))] public class PortalDriver : MonoBehaviour { /// /// The object that will be transported through the portal. Usually either this object or a parent offset object. /// If left empty, it will default to this object. /// public Transform traveller; /// /// Whether this portal driver has a clone mirroring it at other portals. Disable this for the player. /// public bool hasClone = true; /// /// The side of the portal this became tracked on. /// [HideInInspector] public int entrySide; /// /// The clone that is used to mirror this portal driver at another portal. /// [HideInInspector] public PortalDriverClone clone; private Collider _collider; private Rigidbody _rigidbody; private void Awake() { // check whether the collider is set up correctly _collider = GetComponent(); if (_collider.isTrigger) throw new Exception("Collider must not be a trigger."); // check whether the traveller is set if (!traveller) traveller = transform; // get the rigidbody if there is one _rigidbody = GetComponent(); } protected void Start() { if (hasClone) clone = PortalDriverClone.Create(this); } private void Update() { if (hasClone && clone.gameObject.activeSelf) clone.UpdatePosition(transform); } public void EnableClone(Portal at) { if (hasClone) { clone.portal = at; clone.gameObject.SetActive(true); } } public void DisableClone(Portal at) { if (hasClone && at.Equals(clone.portal)) // don't disable clones that are already at a different portal { clone.portal = null; clone.gameObject.SetActive(false); } } public void Teleport(Portal from, Portal to) { var m = to.transform.localToWorldMatrix * Portal.HalfRotation * from.transform.worldToLocalMatrix * traveller.localToWorldMatrix; traveller.SetPositionAndRotation(m.GetPosition(), m.rotation); if (_rigidbody) { _rigidbody.velocity = to.transform.TransformDirection( Portal.HalfRotation.rotation * from.transform.InverseTransformDirection(_rigidbody.velocity)); } } } }