public static SuperspectiveRaycast Raycast(Ray ray, float maxDistance, int layerMask) { SuperspectiveRaycast result = new SuperspectiveRaycast(); result.distance = maxDistance; Ray currentRay = ray; float distanceRemaining = maxDistance; int raycastsMade = 0; Portal lastPortalHit = null; while (distanceRemaining > 0 && raycastsMade < MAX_RAYCASTS) { int lastPortalHitLayer = -1; // Temporarily ignore the out portal of the last portal hit if (lastPortalHit != null && lastPortalHit.otherPortal != null) { lastPortalHitLayer = lastPortalHit.otherPortal.gameObject.layer; lastPortalHit.otherPortal.gameObject.layer = LayerMask.NameToLayer("Ignore Raycast"); } RaycastHit[] hits = Physics.RaycastAll( currentRay.origin, currentRay.direction, distanceRemaining, layerMask, QueryTriggerInteraction.Collide ); raycastsMade++; if (lastPortalHitLayer > 0 && lastPortalHit.otherPortal != null) { lastPortalHit.otherPortal.gameObject.layer = lastPortalHitLayer; } SuperspectiveRaycastPart part = new SuperspectiveRaycastPart(currentRay, distanceRemaining, hits); distanceRemaining -= part.distance; if (part.hitPortal && distanceRemaining > 0) { currentRay = part.NextRay(); lastPortalHit = part.portalHit; } result.AddPart(part); } if (raycastsMade == MAX_RAYCASTS) { Debug.LogWarning($"Max steps for raycast {MAX_RAYCASTS} exceeded, raycast shorted early"); } return(result); }
public void AddPart(SuperspectiveRaycastPart part) { if (part.portalHit != null) { allPortalsHit.Add(part.portalHit); } if (part.objectsHit != null && part.objectsHit.Length > 0) { allObjectHits.AddRange(part.objectsHit); } raycastParts.Add(part); }