Advertisement
Guest User

Untitled

a guest
May 19th, 2017
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.23 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3.  
  4. namespace Pathfinding {
  5.     /** Simplifies a path using raycasting.
  6.      * \ingroup modifiers
  7.      * This modifier will try to remove as many nodes as possible from the path using raycasting (linecasting) to validate the node removal.
  8.      * You can use either graph raycasting or Physics.Raycast.
  9.      * When using graph raycasting, the graph will be traversed and checked for obstacles. When physics raycasting is used, the Unity physics system
  10.      * will be asked if there are any colliders which intersect the line that is currently being checked.
  11.      */
  12.     [AddComponentMenu("Pathfinding/Modifiers/Raycast Simplifier")]
  13.     [RequireComponent(typeof(Seeker))]
  14.     [System.Serializable]
  15.     public class RaycastModifier : MonoModifier {
  16.     #if UNITY_EDITOR
  17.         [UnityEditor.MenuItem("CONTEXT/Seeker/Add Raycast Simplifier Modifier")]
  18.         public static void AddComp (UnityEditor.MenuCommand command) {
  19.             (command.context as Component).gameObject.AddComponent(typeof(RaycastModifier));
  20.         }
  21.     #endif
  22.  
  23.         public override int Order { get { return 40; } }
  24.  
  25.         /** Use Physics.Raycast to simplify the path */
  26.         public bool useRaycasting = true;
  27.  
  28.         /** Layer mask used for physics raycasting */
  29.         public LayerMask mask = -1;
  30.  
  31.         /** Checks around the line between two points, not just the exact line.
  32.          * Make sure the ground is either too far below or is not inside the mask since otherwise the raycast might always hit the ground
  33.          */
  34.         [Tooltip("Checks around the line between two points, not just the exact line.\nMake sure the ground is either too far below or is not inside the mask since otherwise the raycast might always hit the ground.")]
  35.         public bool thickRaycast;
  36.  
  37.         /** Distance from the ray which will be checked for colliders */
  38.         [Tooltip("Distance from the ray which will be checked for colliders")]
  39.         public float thickRaycastRadius;
  40.  
  41.         /** Check for intersections with 2D colliders instead of 3D colliders.
  42.          * Useful for 2D games.
  43.          */
  44.         [Tooltip("Check for intersections with 2D colliders instead of 3D colliders.")]
  45.         public bool use2DPhysics;
  46.  
  47.         /** Offset from the original positions to perform the raycast.
  48.          * Can be useful to avoid the raycast intersecting the ground or similar things you do not want to it intersect
  49.          */
  50.         [Tooltip("Offset from the original positions to perform the raycast.\nCan be useful to avoid the raycast intersecting the ground or similar things you do not want to it intersect")]
  51.         public Vector3 raycastOffset = Vector3.zero;
  52.  
  53.         /** Subdivides the path every iteration to be able to find shorter paths */
  54.         [Tooltip("Subdivides the path every iteration to be able to find shorter paths")]
  55.         public bool subdivideEveryIter;
  56.  
  57.         /** How many iterations to try to simplify the path.
  58.          * If the path is changed in one iteration, the next iteration may find more simplification oppourtunities */
  59.         [Tooltip("How many iterations to try to simplify the path. If the path is changed in one iteration, the next iteration may find more simplification oppourtunities")]
  60.         public int iterations = 2;
  61.  
  62.         /** Use raycasting on the graphs. Only currently works with GridGraph and NavmeshGraph and RecastGraph. \astarpro */
  63.         [Tooltip("Use raycasting on the graphs. Only currently works with GridGraph and NavmeshGraph and RecastGraph. This is a pro version feature.")]
  64.         public bool useGraphRaycasting;
  65.  
  66.         public override void Apply (Path p) {
  67.             if (iterations <= 0) return;
  68.  
  69.             if (!useRaycasting && !useGraphRaycasting) {
  70.                 Debug.LogWarning("RaycastModifier is configured to not use either raycasting or graph raycasting. This would simplify the path to a straight line. The modifier will not be applied.");
  71.                 return;
  72.             }
  73.  
  74.             var points = p.vectorPath;
  75.  
  76.             for (int it = 0; it < iterations; it++) {
  77.                 if (subdivideEveryIter && it != 0) {
  78.                     Subdivide(points);
  79.                 }
  80.  
  81.                 int i = 0;
  82.                 while (i < points.Count-2) {
  83.                     Vector3 start = points[i];
  84.                     Vector3 end = points[i+2];
  85.  
  86.                     if (ValidateLine(null, null, start, end)) {
  87.                         points.RemoveAt(i+1);
  88.                     } else {
  89.                         i++;
  90.                     }
  91.                 }
  92.             }
  93.         }
  94.  
  95.         /** Divides each segment in the list into 3 segments */
  96.         static void Subdivide (List<Vector3> points) {
  97.             if (points.Capacity < points.Count * 3) {
  98.                 points.Capacity = points.Count * 3;
  99.             }
  100.  
  101.             int preLength = points.Count;
  102.  
  103.             for (int j = 0; j < preLength-1; j++) {
  104.                 points.Add(Vector3.zero);
  105.                 points.Add(Vector3.zero);
  106.             }
  107.  
  108.             for (int j = preLength-1; j > 0; j--) {
  109.                 Vector3 p1 = points[j];
  110.                 Vector3 p2 = points[j + 1];
  111.  
  112.                 points[j * 3] = points[j];
  113.  
  114.                 if (j != preLength - 1) {
  115.                     points[j * 3 + 1] = Vector3.Lerp(p1, p2, 0.33F);
  116.                     points[j * 3 + 2] = Vector3.Lerp(p1, p2, 0.66F);
  117.                 }
  118.             }
  119.         }
  120.  
  121.         /** Check if a straight path between v1 and v2 is valid */
  122.         public bool ValidateLine (GraphNode n1, GraphNode n2, Vector3 v1, Vector3 v2) {
  123.             if (useRaycasting) {
  124.                 // Use raycasting to check if a straight path between v1 and v2 is valid
  125.                 if (use2DPhysics) {
  126.                     if (thickRaycast && thickRaycastRadius > 0) {
  127.                         if (Physics2D.CircleCast(v1 + raycastOffset, thickRaycastRadius, v2 - v1, (v2 - v1).magnitude, mask)) {
  128.                             return false;
  129.                         }
  130.                     } else if (Physics2D.Linecast(v1+raycastOffset, v2+raycastOffset, mask)) {
  131.                         return false;
  132.                     }
  133.                 } else {
  134.                     if (thickRaycast && thickRaycastRadius > 0) {
  135.                         if (Physics.SphereCast(new Ray(v1+raycastOffset, v2-v1), thickRaycastRadius, (v2-v1).magnitude, mask)) {
  136.                             return false;
  137.                         }
  138.                     } else if (Physics.Linecast(v1+raycastOffset, v2+raycastOffset, mask)) {
  139.                         return false;
  140.                     }
  141.                 }
  142.             }
  143.  
  144.             if (useGraphRaycasting && n1 == null) {
  145.                 n1 = AstarPath.active.GetNearest(v1).node;
  146.                 n2 = AstarPath.active.GetNearest(v2).node;
  147.             }
  148.  
  149.             if (useGraphRaycasting && n1 != null && n2 != null) {
  150.                 // Use graph raycasting to check if a straight path between v1 and v2 is valid
  151.                 NavGraph graph = AstarData.GetGraph(n1);
  152.                 NavGraph graph2 = AstarData.GetGraph(n2);
  153.  
  154.                 if (graph != graph2) {
  155.                     return false;
  156.                 }
  157.  
  158.                 if (graph != null) {
  159.                     var rayGraph = graph as IRaycastableGraph;
  160.  
  161.                     if (rayGraph != null) {
  162.                         return !rayGraph.Linecast(v1, v2, n1);
  163.                     }
  164.                 }
  165.             }
  166.             return true;
  167.         }
  168.     }
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement