void HandleTravellers() { for (int i = 0; i < trackedTravellers.Count; i++) { PortalTraveller traveller = trackedTravellers[i]; Transform travellerT = traveller.transform; if (!traveller.gameObject.activeSelf || !traveller.collider.bounds.Intersects(collider.bounds)) { traveller.ExitPortalThreshold(); trackedTravellers.Remove(traveller); i--; continue; } var m = linkedPortal.transform.localToWorldMatrix * transform.worldToLocalMatrix * travellerT.localToWorldMatrix; Vector3 offsetFromPortal = travellerT.position - transform.position; int portalSide = System.Math.Sign(Vector3.Dot(offsetFromPortal, transform.forward)); int portalSideOld = System.Math.Sign(Vector3.Dot(traveller.previousOffsetFromPortal, transform.forward)); // Teleport the traveller if it has crossed from one side of the portal to the other if (portalSide != portalSideOld) { var positionOld = travellerT.position; var rotOld = travellerT.rotation; traveller.Teleport(transform, traveller.graphicsClone.transform, m.GetColumn(3), m.rotation, m); traveller.graphicsClone.transform.SetPositionAndRotation(positionOld, rotOld); traveller.graphicsClone.transform.localScale = MyFunc.Div(transform.lossyScale, linkedPortal.transform.lossyScale); // Can't rely on OnTriggerEnter/Exit to be called next frame since it depends on when FixedUpdate runs linkedPortal.OnTravellerEnterPortal(traveller); trackedTravellers.RemoveAt(i); i--; Portal temp = linkedPortal; if (portalController != null) { portalController.OnOutFromPortal(linkedPortal); } if (temp.portalController != null) { temp.portalController.OnComeToPortal(this); } } else { traveller.graphicsClone.transform.SetPositionAndRotation(m.GetColumn(3), m.rotation); traveller.graphicsClone.transform.localScale = MyFunc.Div(m.lossyScale, travellerT.transform.lossyScale); traveller.previousOffsetFromPortal = offsetFromPortal; } } }