private void FixedUpdate() { PortalOcclusionVolume currentOcclusionVolume = null; foreach (var occlusionVolume in occlusionVolumes) { if (occlusionVolume.collider.bounds.Contains(transform.position)) { currentOcclusionVolume = occlusionVolume; break; } } var bestApparentPosition = FindBestApparentPosition( transform.position, target.position, "Player Visibility Checker", layerMask, currentOcclusionVolume, maxRecursions, maxApparentPositions ); if (bestApparentPosition != null) { transform.LookAt(bestApparentPosition.ApparentPosition); } }
private void OnPreRender() { PortalOcclusionVolume currentVolume = null; foreach (PortalOcclusionVolume portalOcclusionVolume in portalOcclusionVolumes) { if (portalOcclusionVolume.collider.bounds.Contains(transform.position)) { currentVolume = portalOcclusionVolume; break; } } Portal[] portalsToRender = currentVolume ? currentVolume.visiblePortals : defaultRenderAllPortals ? allPortals : null; debugDirectPortalCount = 0; if (portalsToRender != null) { foreach (Portal portal in portalsToRender) { // Frustum cull; do not render portal view through texture if not visible if (portal.viewThroughToRenderer.isVisible) { Portal.RenderViewThroughRecursive( portal, GameManager.instance.mainCamera.transform.position, GameManager.instance.mainCamera.transform.rotation, out PortalRenderTexturePoolItem _, out Texture _, out int renderCount); debugDirectPortalCount++; debugTotalPortalCount = renderCount; } } } }
private void OnPreRender() { debugTotalRenderCount = 0; PortalOcclusionVolume currentOcclusionVolume = null; foreach (var occlusionVolume in occlusionVolumes) { if (occlusionVolume.collider.bounds.Contains(mainCamera.transform.position)) { currentOcclusionVolume = occlusionVolume; break; } } if (currentOcclusionVolume != null) { var cameraPlanes = GeometryUtility.CalculateFrustumPlanes(mainCamera); foreach (var portal in currentOcclusionVolume.portals) { if (!portal.ShouldRender(cameraPlanes)) { continue; } portal.RenderViewthroughRecursive( mainCamera.transform.position, mainCamera.transform.rotation, out _, out _, out var renderCount, portalCamera, 0, maxRecursions, noCloneMask, renderCloneMask, PortalableObjectClone.LocalInstance.ClosestTouchingPortal); debugTotalRenderCount += renderCount; } } }
private void OnPreRender() { DebugTotalRenderCount = 0; PortalOcclusionVolume currentOcclusionVolume = null; foreach (var occlusionVolume in occlusionVolumes) { if (occlusionVolume.Collider.bounds.Contains(mainCamera.transform.position)) { currentOcclusionVolume = occlusionVolume; break; } } if (currentOcclusionVolume != null) { var cameraPlanes = GeometryUtility.CalculateFrustumPlanes(mainCamera); foreach (var portal in currentOcclusionVolume.Portals) { if (!portal.ShouldRender(cameraPlanes)) { continue; } if (portal.TargetPortal[portal.TargetPortalIndex] != null) { portal.RenderViewthroughRecursive( mainCamera.transform.position, mainCamera.transform.rotation, out _, out _, out var renderCount, PortalCamera, 0, MaxRecursions); DebugTotalRenderCount += renderCount; } } } }
public static TargetApparentPosition FindBestApparentPosition( Vector3 origin, Vector3 target, string targetTag, LayerMask layerMask, PortalOcclusionVolume occlusionVolume, int maxRecursions, int maxApparentPositions) { AimingPortalChainQueue.Clear(); AimingTargetApparentPositions.Clear(); // Breadth first search AimingPortalChainQueue.Enqueue(new List <Portal>()); while (AimingPortalChainQueue.Count > 0) { var currentChain = AimingPortalChainQueue.Dequeue(); // Calculate apparent location var targetApparentPosition = target; foreach (var portal in currentChain) { targetApparentPosition = Portal.TransformPositionBetweenPortals(portal.targetPortal, portal, targetApparentPosition); } var aimDirection = targetApparentPosition - origin; aimDirection.Normalize(); // Calculate visibility // If visible, add to target apparent positions if (Portal.RaycastRecursive( origin, aimDirection, currentChain.Count, null, (x, y) => layerMask, out var hitInfo)) { if (hitInfo.collider.CompareTag(targetTag)) { AimingTargetApparentPositions.Add(new TargetApparentPosition { ApparentPosition = targetApparentPosition, AimDirection = aimDirection }); } } // Return if enough for an accurate heuristic if (maxApparentPositions > 0) { if (AimingTargetApparentPositions.Count >= maxApparentPositions) { break; } } // Continue search; add to queue if (currentChain.Count >= maxRecursions) { continue; } foreach (var visiblePortal in currentChain.Count > 0 ? currentChain[currentChain.Count - 1].visiblePortals : occlusionVolume == null ? new Portal[0] : occlusionVolume.portals) { AimingPortalChainQueue.Enqueue(new List <Portal>(currentChain) { visiblePortal }); } } // Use heuristic (closest apparent) to find which of the apparent positions should the AI shoot at TargetApparentPosition bestApparentPosition = null; var minDistance = Mathf.Infinity; foreach (var aimingTargetApparentPosition in AimingTargetApparentPositions) { var distance = Vector3.Distance(aimingTargetApparentPosition.ApparentPosition, origin); if (distance >= minDistance) { continue; } minDistance = distance; bestApparentPosition = aimingTargetApparentPosition; } return(bestApparentPosition); }