// Handles collision exit events sent from either portal. Happens when an object ends contact w/ portal. // If the object isnt moving very fast, we want to wait to allow it to be portaled again. // This is because multiple exit trigger events may be fired before it has really ended contact with the exit portal. // If we release the lock early, then it could immediately be portaled back to the entry portal, and then ping pong between portals. public void handleTriggerExit(GameObject portal, GameObject colliderGO) { ObjectPortalState currentObject = getObjectFromCollisionObjectInstanceID(colliderGO.GetInstanceID()); if (currentObject == null || currentObject.currentEntryPortal == null || currentObject.currentExitPortal == null) { return; } // If the exit portal sent a triggerExit event, start a coroutine to wait until triggerexit events stop // Once they stop, then the object is reset if (currentObject.currentExitPortal.GetInstanceID() == portal.GetInstanceID()) { float speedThreshold = 1.3f; // Dont bother checking triggers if it's moving fast enough Rigidbody rb = currentObject.currentCollisionObject.GetComponent <Rigidbody>(); if (rb != null && rb.velocity.magnitude >= speedThreshold) { currentObject.allowPortaling(); } else { currentObject.portalExitLock = true; if (!currentObject.verifyingExitTrigger) { StartCoroutine(currentObject.verifyExitTrigger()); } } } }
// Handles collision enter events sent from either portal. Happens when an object makes contact w/ portal. // Finds the localCollisionPosition: // Tell the collider to fire a ray in its forward direction to get the point of collision at the entry portal. // Also use this to determine whether the object is actually aiming at the portal or not. // Don't translate the object if it grazes the edge of the portal box collider // Creates ObjectPortalState object with the current portals and gameObject state, // then calls translateBetweenPortals() to move the object to the exit portal, where handleTriggerExit() should eventually do the rest. public void handleTriggerEnter(GameObject entryPortal, GameObject colliderGO) { ObjectPortalState current = getObjectFromCollisionObjectInstanceID(colliderGO.GetInstanceID()); // Dont start over if there's already an entry portal assigned. if (current != null && current.currentEntryPortal != null) { return; } if (colliderGO.tag == colliderGOtag && portalGOs.Length > 1) { GameObject exitPortal = getOtherPortal(entryPortal); if (exitPortal == null) { return; } Vector3 localCollisionPosition = getCollisionPointAtEntryPortal(colliderGO, entryPortal); if (localCollisionPosition == Vector3.zero) { return; } if (current == null) { current = new ObjectPortalState(); } current.currentExitPortal = exitPortal; current.currentEntryPortal = entryPortal; current.currentCollisionObject = colliderGO; portalObjects.Add(current); translateBetweenPortals(colliderGO, exitPortal, entryPortal, localCollisionPosition); } }
// Go through list of ObjectPortalState objects and return the one containing the currentCollisionObject with the specified id. // If not found, returns null. private ObjectPortalState getObjectFromCollisionObjectInstanceID(int id) { ObjectPortalState objps = portalObjects.Find(x => x.currentCollisionObject.GetInstanceID() == id); return(objps); }