253 lines
10 KiB
C#
253 lines
10 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace Fragilem17.MirrorsAndPortals
|
|
{
|
|
/**
|
|
* Used to transport PortalableObjects to the linked portal defined in the portalSurface
|
|
*/
|
|
public class PortalTransporter : MonoBehaviour
|
|
{
|
|
private Portal _portal;
|
|
public List<PortalableObject> portalableObjects = new List<PortalableObject>();
|
|
//private List<CloneRenderer> cloneObjects = new List<CloneRenderer>();
|
|
public HashSet<CloneRenderer> cloneObjects = new HashSet<CloneRenderer>();
|
|
public HashSet<CloneRenderer> cloneObjectsActuallyTouching = new HashSet<CloneRenderer>();
|
|
public HashSet<CloneRenderer> cloneObjectsToRemove = new HashSet<CloneRenderer>();
|
|
private List<PortalAffectorSphere> portalAffectorSpheres = new List<PortalAffectorSphere>();
|
|
private Vector3 _originalScale;
|
|
|
|
[Space(10)]
|
|
[Header("Events")]
|
|
public UnityEvent<PortalableObject> OnObjectEnteredPortal;
|
|
public UnityEvent<PortalableObject> OnObjectTransportedAwayFromHere;
|
|
public UnityEvent<PortalableObject> OnObjectTransportedToHere;
|
|
public UnityEvent<PortalableObject> OnObjectExitedPortal;
|
|
|
|
[HideInInspector]
|
|
public Collider MyCollider;
|
|
|
|
public enum PortalReason {
|
|
Undefined,
|
|
ExitedCurrentPortalCollider,
|
|
EnteredOtherPortalCollider
|
|
}
|
|
|
|
public Portal Portal { get => _portal; }
|
|
|
|
public void Initialise()
|
|
{
|
|
MyCollider = GetComponent<Collider>();
|
|
if (!MyCollider)
|
|
{
|
|
Debug.LogWarning(PortalUtils.Colorize("[PORTALS] ", PortalUtils.DebugColors.Warn, true) + name + " has a PortalTransporter Component but no trigger Collider, add a big enough Collider for things to hit it before reaching the actual portal.");
|
|
}
|
|
else
|
|
{
|
|
MyCollider.isTrigger = true;
|
|
}
|
|
|
|
Rigidbody rb = GetComponent<Rigidbody>();
|
|
if (!rb)
|
|
{
|
|
Debug.LogWarning(PortalUtils.Colorize("[PORTALS] ", PortalUtils.DebugColors.Warn, true) + name + " has a PortalTransporter Component but no RigidBody Component. Add a (Kinematic) Rigidbody Component to this GameObject.");
|
|
}
|
|
|
|
_portal = GetComponentInParent<Portal>();
|
|
if (!_portal)
|
|
{
|
|
Debug.LogWarning(PortalUtils.Colorize("[PORTALS] ", PortalUtils.DebugColors.Warn, true) + name + " has a PortalTransporter Component but no Portal Component, add a Portal Component to this or a parent GameObject.");
|
|
}
|
|
}
|
|
|
|
protected void OnEnable()
|
|
{
|
|
Initialise();
|
|
}
|
|
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
//CheckNeedPortal();
|
|
}
|
|
|
|
|
|
private void LateUpdate()
|
|
{
|
|
//CheckNeedPortal();
|
|
}
|
|
|
|
protected void Update()
|
|
{
|
|
CheckNeedPortal();
|
|
}
|
|
|
|
protected void CheckNeedPortal()
|
|
{
|
|
PortalableObject p = null;
|
|
for (int i = 0; i < portalableObjects.Count; ++i)
|
|
{
|
|
p = portalableObjects[i];
|
|
if (p)
|
|
{
|
|
Vector3 objPos = _portal.PortalSurface.transform.InverseTransformPoint(p.transform.position);
|
|
|
|
if (objPos.z > 0)
|
|
{
|
|
PortalableObject po = portalableObjects[i];
|
|
if (po.CanPortal())
|
|
{
|
|
//Debug.Log("PortalTransporter " + Portal.name + " : fixedUpdate z > 0 - doing portal on " + po.name + " : " + objPos.z);
|
|
|
|
if (_portal.OtherPortal && _portal.OtherPortal.PortalTransporter)
|
|
{
|
|
// only trigger the ExternalTriggerEnter if we're actually telepoting inside our collider!
|
|
_portal.OtherPortal.PortalTransporter.ExternalTriggerEnter(po.gameObject, false);
|
|
_portal.OtherPortal.PortalTransporter.OnObjectTransportedToHere.Invoke(po);
|
|
}
|
|
po.PortalFrom(_portal);
|
|
OnObjectTransportedAwayFromHere.Invoke(po);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public void ExternalTriggerEnter(GameObject other, bool fromPhysics = false)
|
|
{
|
|
// first trigger the exit in the other portal
|
|
if (!fromPhysics && _portal.OtherPortal && _portal.OtherPortal.PortalTransporter)
|
|
{
|
|
_portal.OtherPortal.PortalTransporter.ExternalTriggerExit(other, fromPhysics, PortalReason.EnteredOtherPortalCollider);
|
|
}
|
|
|
|
Vector3 objPos = _portal.PortalSurface.transform.InverseTransformPoint(other.transform.position);
|
|
// did we enter in front of the portal?
|
|
//Debug.Log("ExternalTriggerEnter objPos: " + other.name + " " + objPos.z + " " + fromPhysics + " :" + Portal.name);
|
|
if (!fromPhysics || (fromPhysics && objPos.z < 0))
|
|
{
|
|
PortalableObject obj = other.GetComponent<PortalableObject>();
|
|
if (obj && obj.isActiveAndEnabled && !portalableObjects.Contains(obj))
|
|
{
|
|
//Debug.Log("Adding to portal list of " + _portal.name + " object:" + other.name);
|
|
portalableObjects.Add(obj);
|
|
//obj.OnExitPortalCollider.AddListener(onPortalableObjectExitPortalCollider);
|
|
|
|
obj.SetIsInPortal(_portal);
|
|
OnObjectEnteredPortal.Invoke(obj);
|
|
}
|
|
else
|
|
{
|
|
PortalableObjectCollider helper = other.GetComponent<PortalableObjectCollider>();
|
|
if (helper && helper.isActiveAndEnabled && !portalableObjects.Contains(helper.PortalableObject))
|
|
{
|
|
//Debug.Log("Adding to portal list of " + _portal.name + " object:" + other.name);
|
|
portalableObjects.Add(helper.PortalableObject);
|
|
//obj.OnExitPortalCollider.AddListener(onPortalableObjectExitPortalCollider);
|
|
|
|
helper.PortalableObject.SetIsInPortal(_portal);
|
|
OnObjectEnteredPortal.Invoke(helper.PortalableObject);
|
|
}
|
|
}
|
|
|
|
|
|
CloneRenderer cloneObject = other.GetComponent<CloneRenderer>();
|
|
if (cloneObject && cloneObject.isActiveAndEnabled && !cloneObjects.Contains(cloneObject))
|
|
{
|
|
cloneObjects.Add(cloneObject);
|
|
cloneObject.SetIsInPortal(_portal, true);
|
|
}
|
|
|
|
PortalAffectorSphere affectorSphere = other.GetComponent<PortalAffectorSphere>();
|
|
if (affectorSphere && affectorSphere.isActiveAndEnabled && !portalAffectorSpheres.Contains(affectorSphere))
|
|
{
|
|
//if (fromPhysics)
|
|
//{
|
|
portalAffectorSpheres.Add(affectorSphere);
|
|
//}
|
|
affectorSphere.SetIsInPortal(_portal);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*private void onPortalableObjectExitPortalCollider(PortalableObject obj, Portal p)
|
|
{
|
|
if (p == Portal)
|
|
{
|
|
ExternalTriggerExit(obj.gameObject, false);
|
|
}
|
|
}*/
|
|
|
|
public void ExternalTriggerExit(GameObject other, bool fromPhysics = false, PortalReason reason = PortalReason.Undefined)
|
|
{
|
|
PortalableObject portalableObj = other.GetComponent<PortalableObject>();
|
|
|
|
/*
|
|
bool isPortallingAlongWithMasterPortalable = false;
|
|
if (portalableObj) {
|
|
//portalableObj.OnExitPortalCollider.RemoveListener(onPortalableObjectExitPortalCollider);
|
|
isPortallingAlongWithMasterPortalable = portalableObj.EnablePortalAlongWithMasterPortalable;
|
|
}
|
|
|
|
// todo: as long as we're grabbing something, and it's gonna portal along with the player, then don't exit the portal when it's collider exits this transporter.
|
|
// but, what to do when the player does not portal?
|
|
if (reason == PortalReason.ExitedCurrentPortalCollider && isPortallingAlongWithMasterPortalable)
|
|
{
|
|
// are we on the other side of the surface when exiting the collider? then keep it inside the portal
|
|
Vector3 objPos = _portal.PortalSurface.transform.InverseTransformPoint(other.transform.position);
|
|
Debug.Log("objPos: " + objPos.z);
|
|
if (objPos.z > 0)
|
|
{
|
|
return;
|
|
}
|
|
}*/
|
|
|
|
|
|
CloneRenderer cloneObject = other.GetComponent<CloneRenderer>();
|
|
/*if (cloneObject)
|
|
{
|
|
Debug.Log(cloneObject.name + " exits portal " + Portal.name + " IF " + cloneObjects.Contains(cloneObject) + " AND NOT isPortallingAlongWithMasterPortalable: " + isPortallingAlongWithMasterPortalable);
|
|
}*/
|
|
|
|
if (cloneObject && cloneObjects.Contains(cloneObject))
|
|
{
|
|
cloneObjects.Remove(cloneObject);
|
|
cloneObject.ExitPortal(_portal, fromPhysics);
|
|
}
|
|
|
|
if (portalableObj && portalableObjects.Contains(portalableObj))
|
|
{
|
|
//Debug.Log("Exit Portal " + gameObject.name);
|
|
//Debug.Log("Removing from portal list of " + _portal.name + " object:" + other.name);
|
|
//Debug.Log("PortalableObject " + portalableObj.name + " ExitsPortal: " + _portal.name + " fromPhysics: " + fromPhysics);
|
|
portalableObjects.Remove(portalableObj);
|
|
portalableObj.ExitPortal(_portal);
|
|
OnObjectExitedPortal.Invoke(portalableObj);
|
|
}
|
|
|
|
PortalAffectorSphere affectorSphere = other.GetComponent<PortalAffectorSphere>();
|
|
if (affectorSphere && portalAffectorSpheres.Contains(affectorSphere))
|
|
{
|
|
portalAffectorSpheres.Remove(affectorSphere);
|
|
affectorSphere.ExitPortal(_portal);
|
|
}
|
|
}
|
|
|
|
protected void OnTriggerEnter(Collider other)
|
|
{
|
|
//Debug.Log("OnTriggerEnter: " + other.name);
|
|
ExternalTriggerEnter(other.gameObject, true);
|
|
}
|
|
|
|
protected void OnTriggerExit(Collider other)
|
|
{
|
|
ExternalTriggerExit(other.gameObject, true, PortalReason.ExitedCurrentPortalCollider);
|
|
}
|
|
}
|
|
} |