Beispiel #1
0
    /// <summary>
    /// copy from AstarPathEditor, because can't access Editor code here
    /// </summary>
    public static void MenuScan()
    {
        if (AstarPath.active == null)
        {
            AstarPath.active = FindObjectOfType(typeof(AstarPath)) as AstarPath;
            if (AstarPath.active == null)
            {
                return;
            }
        }

        if (!Application.isPlaying && (AstarPath.active.astarData.graphs == null || AstarPath.active.astarData.graphTypes == null))
        {
            UnityEditor.EditorUtility.DisplayProgressBar("Scanning", "Deserializing", 0);
            AstarPath.active.astarData.DeserializeGraphs();
        }

        UnityEditor.EditorUtility.DisplayProgressBar("Scanning", "Scanning...", 0);

        try
        {
            OnScanStatus info = progress => UnityEditor.EditorUtility.DisplayProgressBar("Scanning", progress.description, progress.progress);
            AstarPath.active.ScanLoop(info);
        }
        catch (System.Exception e)
        {
            EB.Debug.LogError("There was an error generating the graphs:\n" + e + "\n\nIf you think this is a bug, please contact me on arongranberg.com (post a comment)\n");
            UnityEditor.EditorUtility.DisplayDialog("Error Generating Graphs", "There was an error when generating graphs, check the console for more info", "Ok");
            throw e;
        }
        finally
        {
            UnityEditor.EditorUtility.ClearProgressBar();
        }
    }
Beispiel #2
0
        protected void ScanTiledNavmesh(OnScanStatus statusCallback)
        {
#if BNICKSON_UPDATED
            if (generateFromInputMesh)
            {
                AStarPathfindingWalkableArea[] walkAreas = GameObject.FindObjectsOfType(typeof(AStarPathfindingWalkableArea)) as AStarPathfindingWalkableArea[];
                if (isSingleInputMesh)
                {
                    if (1 == walkAreas.Length)
                    {
                        GenerateTileFromInputMesh(walkAreas[0]);
                    }
                }
                else
                {
                    GenerateTilesForZones(walkAreas);
                }
            }
            else
            {
                ScanAllTiles(statusCallback);
            }
#else
            ScanAllTiles(statusCallback);
#endif
        }
Beispiel #3
0
 public void ScanLoop(OnScanStatus statusCallback)
 {
     foreach (Progress progress in this.ScanAsync(null))
     {
         statusCallback(progress);
     }
 }
Beispiel #4
0
 public override void ScanInternal(OnScanStatus statusCallback)
 {
     if (this.sourceMesh == null)
     {
         return;
     }
     this.GenerateMatrix();
     Vector3[] vertices = this.sourceMesh.vertices;
     this.triangles = this.sourceMesh.triangles;
     TriangleMeshNode.SetNavmeshHolder(this.active.astarData.GetGraphIndex(this), this);
     this.GenerateNodes(vertices, this.triangles, out this.originalVertices, out this._vertices);
 }
        public void ScanInternal(OnScanStatus statusCallback)
        {
            if (sourceMesh == null)
            {
                return;
            }

            GenerateMatrix();

            Vector3[] vectorVertices = sourceMesh.vertices;

            triangles = sourceMesh.triangles;

            TriangleMeshNode.SetNavmeshHolder(active.astarData.GetGraphIndex(this), this);
            GenerateNodes(vectorVertices, triangles, out originalVertices, out _vertices);
        }
Beispiel #6
0
    public override void ScanInternal(OnScanStatus statusCallback)
    {
        // Create a matrix which just moves the nodes and scales their positions by #scale
        // The SetMatrix call will save it to a variable called just "matrix"
        SetMatrix(Matrix4x4.TRS(bottomLeftCorner, Quaternion.identity, Vector3.one * scale));

        // Create an array containing all nodes
        nodes = CreateNodes();

        // Now all nodes are created, let's create some connections between them!
        for (int i = 0; i < nodes.GetLength(0); i++)
        {
            for (int j = 0; j < nodes.GetLength(1); j++)
            {
                SetUpNodeConnections(i, j);
            }
        }
    }
Beispiel #7
0
        public override void ScanInternal(OnScanStatus statusCallback)
        {
            if (sourceMesh == null)
            {
                return;
            }

            GenerateMatrix();

            //float startTime = 0;//Time.realtimeSinceStartup;

            var vectorVertices = sourceMesh.vertices;

            triangles = sourceMesh.triangles;

            TriangleMeshNode.SetNavmeshHolder(active.astarData.GetGraphIndex(this), this);
            GenerateNodes(vectorVertices, triangles, out originalVertices, out _vertices);
        }
Beispiel #8
0
        public override void ScanInternal(OnScanStatus statusCallback)
        {
            this.Width  = 1 << this.editorWidthLog2;
            this.Height = 1 << this.editorHeightLog2;
            this.map    = new BitArray(this.Width * this.Height);
            for (int i = 0; i < this.Width; i++)
            {
                for (int j = 0; j < this.Height; j++)
                {
                    this.map.Set(i + j * this.Width, this.CheckCollision(i, j));
                }
            }
            QuadtreeNodeHolder holder = new QuadtreeNodeHolder();

            this.CreateNodeRec(holder, 0, 0, 0);
            this.root = holder;
            this.RecalculateConnectionsRec(this.root, 0, 0, 0);
        }
		public void ScanInternal (OnScanStatus statusCallback) {
			Width = 1 << editorWidthLog2;
			Height = 1 << editorHeightLog2;
			/** \todo Check if can clear */
			map = new BitArray(Width*Height);

			for (int x=0;x<Width;x++) {
				for (int y=0;y<Height;y++) {
					map.Set(x+y*Width, CheckCollision (x,y));
				}
			}

			var h = new QuadtreeNodeHolder();

			CreateNodeRec (h, 0, 0,0);
			root = h;

			RecalculateConnectionsRec (root, 0,0,0);
		}
        public void ScanInternal(OnScanStatus statusCallback)
        {
            Width  = 1 << editorWidthLog2;
            Height = 1 << editorHeightLog2;
            /** \todo Check if can clear */
            map = new BitArray(Width * Height);

            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    map.Set(x + y * Width, CheckCollision(x, y));
                }
            }

            var h = new QuadtreeNodeHolder();

            CreateNodeRec(h, 0, 0, 0);
            root = h;

            RecalculateConnectionsRec(root, 0, 0, 0);
        }
Beispiel #11
0
		/// <summary>
		/// Scans the graph, called from <see cref="AstarPath.ScanInternal"/>
		/// Override this function to implement custom scanning logic
		/// The statusCallback may be optionally called to show progress info in the editor
		/// </summary>
		public abstract void ScanInternal (OnScanStatus statusCallback);
		public override void ScanInternal (OnScanStatus statusCallback) {
			
			if (sourceMesh == null) {
				return;
			}
			
			GenerateMatrix ();
			
			//float startTime = 0;//Time.realtimeSinceStartup;
			
			Vector3[] vectorVertices = sourceMesh.vertices;
			
			triangles = sourceMesh.triangles;
			
			TriangleMeshNode.SetNavmeshHolder (active.astarData.GetGraphIndex(this),this);
			GenerateNodes (vectorVertices,triangles, out originalVertices, out _vertices);
		
		}
Beispiel #13
0
		public override void ScanInternal (OnScanStatus statusCallback) {
			AstarPath.OnPostScan += new OnScanDelegate(OnPostScan);

			if (nodeSize <= 0) {
				return;
			}

			// Make sure the matrix is up to date
			GenerateMatrix();

			if (width > 1024 || depth > 1024) {
				Debug.LogError("One of the grid's sides is longer than 1024 nodes");
				return;
			}


			SetUpOffsetsAndCosts();

			// Get the graph index of this graph
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);

			// Set a global reference to this graph so that nodes can find it
			GridNode.SetGridGraph(graphIndex, this);

			// Create all nodes
			nodes = new GridNode[width*depth];
			for (int i = 0; i < nodes.Length; i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}

			// Create and initialize the collision class
			if (collision == null) {
				collision = new GraphCollision();
			}
			collision.Initialize(matrix, nodeSize);


			for (int z = 0; z < depth; z++) {
				for (int x = 0; x < width; x++) {
					var node = nodes[z*width+x];

					node.NodeInGridIndex = z*width+x;

					// Updates the position of the node
					// and a bunch of other things
					UpdateNodePositionCollision(node, x, z);
				}
			}

			for (int z = 0; z < depth; z++) {
				for (int x = 0; x < width; x++) {
					var node = nodes[z*width + x];
					// Recalculate connections to other nodes
					CalculateConnections(x, z, node);
				}
			}

			// Apply erosion
			ErodeWalkableArea();
		}
Beispiel #14
0
		protected void ScanAllTiles (OnScanStatus statusCallback) {
			
#if ASTARDEBUG
			Console.WriteLine ("Recast Graph -- Collecting Meshes");
#endif	
			
			AstarProfiler.StartProfile ("Finding Meshes");
			List<ExtraMesh> extraMeshes;
			
			System.Console.WriteLine ("Collecting Meshes");
			
			CollectMeshes (out extraMeshes, forcedBounds);
			
			AstarProfiler.EndProfile ("Finding Meshes");
			
			//----
			
			//Voxel grid size
			int gw = (int)(forcedBounds.size.x/cellSize + 0.5f);
			int gd = (int)(forcedBounds.size.z/cellSize + 0.5f);
			
			if (!useTiles) {
				tileSizeX = gw;
				tileSizeZ = gd;
			} else {
				tileSizeX = editorTileSize;
				tileSizeZ = editorTileSize;
			}
			
			//Number of tiles
			int tw = (gw + tileSizeX-1) / tileSizeX;
			int td = (gd + tileSizeZ-1) / tileSizeZ;
			
			tileXCount = tw;
			tileZCount = td;
			
			if (tileXCount * tileZCount > TileIndexMask+1) {
				throw new System.Exception ("Too many tiles ("+(tileXCount * tileZCount)+") maximum is "+(TileIndexMask+1)+
					"\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector.");
			}
			
			tiles = new NavmeshTile[tileXCount*tileZCount];
			
#if ASTARDEBUG
			Console.WriteLine ("Recast Graph -- Creating Voxel Base");
#endif
			
			//Create the voxelizer and set all settings
			Voxelize vox = new Voxelize (cellHeight, cellSize, walkableClimb, walkableHeight, maxSlope);
			vox.inputExtraMeshes = extraMeshes;
			
			vox.maxEdgeLength = maxEdgeLength;
			
			int lastUp = -1;
			System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
			watch.Start();
			
			//Generate all tiles
			for (int z=0;z<td;z++) {
				for (int x=0;x<tw;x++) {
					
					int tileNum = z*tileXCount + x;
					System.Console.WriteLine ("Generating Tile #"+(tileNum) + " of " + td*tw);
					
					//Call statusCallback only 10 times since it is very slow in the editor
					if ((tileNum*10/tiles.Length > lastUp || watch.ElapsedMilliseconds > 2000) && statusCallback != null) {
						lastUp = tileNum*10/tiles.Length;
						watch.Reset();
						watch.Start();
						
						statusCallback (new Progress (AstarMath.MapToRange (0.1f, 0.9f, tileNum/(float)tiles.Length), "Building Tile " + tileNum + "/" + tiles.Length));
					}
					
					BuildTileMesh (vox, x,z);
				}
			}
			
			System.Console.WriteLine ("Assigning Graph Indices");
			if (statusCallback != null) statusCallback (new Progress (0.9f, "Connecting tiles"));
			
			//Assign graph index to nodes
			uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex (this);
			
			GraphNodeDelegateCancelable del = delegate (GraphNode n) {
				n.GraphIndex = graphIndex;
				return true;
			};
			GetNodes (del);
			
			for (int z=0;z<td;z++) {
				for (int x=0;x<tw;x++) {
					System.Console.WriteLine ("Connecing Tile #"+(z*tileXCount + x) + " of " + td*tw);
					if (x < tw-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x+1 + z*tileXCount]);
					if (z < td-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x + (z+1)*tileXCount]);
				}
			}
			
			AstarProfiler.PrintResults ();
		}
Beispiel #15
0
		protected void ScanTiledNavmesh (OnScanStatus statusCallback) {
			ScanAllTiles (statusCallback);
			
		}
		public override void ScanInternal (OnScanStatus statusCallback) {

			if (nodeSize <= 0) {
				return;
			}

			GenerateMatrix ();

			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}

			lastScannedWidth = width;
			lastScannedDepth = depth;

			SetUpOffsetsAndCosts ();

			LevelGridNode.SetGridGraph (active.astarData.GetGraphIndex(this), this);

			maxClimb = Mathf.Clamp (maxClimb,0,characterHeight);

			var linkedCells = new LinkedLevelCell[width*depth];

			collision = collision ?? new GraphCollision ();
			collision.Initialize (matrix,nodeSize);

			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {

					linkedCells[z*width+x] = new LinkedLevelCell ();

					LinkedLevelCell llc = linkedCells[z*width+x];

					Vector3 pos = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));


					RaycastHit[] hits = collision.CheckHeightAll (pos);

					for (int i=0;i<hits.Length/2;i++) {
						RaycastHit tmp = hits[i];

						hits[i] = hits[hits.Length-1-i];
						hits[hits.Length-1-i] = tmp;
					}

					if (hits.Length > 0) {

						LinkedLevelNode lln = null;

						for (int i=0;i<hits.Length;i++) {

							var tmp = new LinkedLevelNode ();
							tmp.position = hits[i].point;

							if (lln != null) {
								/** \todo Use hit.distance instead */
								if (tmp.position.y - lln.position.y <= mergeSpanRange) {
										lln.position = tmp.position;
										lln.hit = hits[i];
										lln.walkable = collision.Check (tmp.position);
									continue;
								}
							}

							tmp.walkable = collision.Check (tmp.position);
							tmp.hit = hits[i];
							tmp.height = float.PositiveInfinity;

							if (llc.first == null) {
								llc.first = tmp;
								lln = tmp;
							} else {
								lln.next = tmp;

								lln.height = tmp.position.y - lln.position.y;
								lln = lln.next;
							}

						}
					} else {
						var lln = new LinkedLevelNode ();
						lln.position = pos;
						lln.height = float.PositiveInfinity;
						lln.walkable = !collision.unwalkableWhenNoGround;
						llc.first = lln;
					}
				}
			}


			int spanCount = 0;
			layerCount = 0;
			// Count the total number of nodes in the graph
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {

					LinkedLevelCell llc = linkedCells[z*width+x];

					LinkedLevelNode lln = llc.first;
					int cellCount = 0;
					// Loop through all nodes in this cell
					do {
						cellCount++;
						spanCount++;
						lln = lln.next;
					} while (lln != null);

					layerCount = cellCount > layerCount ? cellCount : layerCount;
				}
			}

			if (layerCount > LevelGridNode.MaxLayerCount) {
				Debug.LogError ("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found "+layerCount+")");
				return;
			}

			// Create all nodes
			nodes = new LevelGridNode[width*depth*layerCount];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new LevelGridNode (active);
				nodes[i].Penalty = initialPenalty;
			}

			int nodeIndex = 0;

			// Max slope in cosinus
			float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);

			for (int z = 0; z < depth; z++) {
				for (int x = 0; x < width; x++) {

					LinkedLevelCell llc = linkedCells[z*width+x];
					LinkedLevelNode lln = llc.first;

					llc.index = nodeIndex;

					int count = 0;
					int layerIndex = 0;
					do {
						var node = nodes[z*width+x + width*depth*layerIndex];
#if ASTAR_SET_LEVELGRIDNODE_HEIGHT
						node.height = lln.height;
#endif
						node.SetPosition ((Int3)lln.position);
						node.Walkable = lln.walkable;

						// Adjust penalty based on the surface slope
						if (lln.hit.normal != Vector3.zero && (penaltyAngle || cosAngle < 1.0f)) {
							//Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle)
							float angle = Vector3.Dot (lln.hit.normal.normalized,collision.up);

							// Add penalty based on normal
							if (penaltyAngle) {
								node.Penalty += (uint)Mathf.RoundToInt ((1F-angle)*penaltyAngleFactor);
							}

							// Check if the slope is flat enough to stand on
							if (angle < cosAngle) {
								node.Walkable = false;
							}
						}

						node.NodeInGridIndex = z*width+x;

						if (lln.height < characterHeight) {
							node.Walkable = false;
						}

						node.WalkableErosion = node.Walkable;

						nodeIndex++;
						count++;
						lln = lln.next;
						layerIndex++;
					} while (lln != null);

					for (;layerIndex<layerCount;layerIndex++) {
						nodes[z*width+x + width*depth*layerIndex] = null;
					}

					llc.count = count;
				}
			}

			nodeIndex = 0;

			nodeCellIndices = new int[linkedCells.Length];

			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					for (int i=0;i<layerCount;i++) {
						GraphNode node = nodes[z*width+x + width*depth*i];
						CalculateConnections (nodes,node,x,z,i);
					}
				}
			}

			uint graphIndex = (uint)active.astarData.GetGraphIndex(this);

			for (int i=0;i<nodes.Length;i++) {
				var lgn = nodes[i];
				if (lgn == null) continue;

				UpdatePenalty (lgn);

				lgn.GraphIndex = graphIndex;

				// Set the node to be unwalkable if it hasn't got any connections
				if (!lgn.HasAnyGridConnections ()) {
					lgn.Walkable = false;
					lgn.WalkableErosion = lgn.Walkable;
				}
			}

			ErodeWalkableArea ();
		}
Beispiel #17
0
 protected void ScanAllTiles(OnScanStatus statusCallback)
 {
     int num = (int)(this.forcedBounds.size.x / this.cellSize + 0.5f);
     int num2 = (int)(this.forcedBounds.size.z / this.cellSize + 0.5f);
     if (!this.useTiles)
     {
         this.tileSizeX = num;
         this.tileSizeZ = num2;
     }
     else
     {
         this.tileSizeX = this.editorTileSize;
         this.tileSizeZ = this.editorTileSize;
     }
     int num3 = (num + this.tileSizeX - 1) / this.tileSizeX;
     int num4 = (num2 + this.tileSizeZ - 1) / this.tileSizeZ;
     this.tileXCount = num3;
     this.tileZCount = num4;
     if (this.tileXCount * this.tileZCount > 524288)
     {
         throw new Exception(string.Concat(new object[]
         {
             "Too many tiles (",
             this.tileXCount * this.tileZCount,
             ") maximum is ",
             524288,
             "\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector."
         }));
     }
     this.tiles = new RecastGraph.NavmeshTile[this.tileXCount * this.tileZCount];
     if (this.scanEmptyGraph)
     {
         for (int i = 0; i < num4; i++)
         {
             for (int j = 0; j < num3; j++)
             {
                 this.tiles[i * this.tileXCount + j] = RecastGraph.NewEmptyTile(j, i);
             }
         }
         return;
     }
     Console.WriteLine("Collecting Meshes");
     List<ExtraMesh> inputExtraMeshes;
     this.CollectMeshes(out inputExtraMeshes, this.forcedBounds);
     this.walkableClimb = Mathf.Min(this.walkableClimb, this.walkableHeight);
     Voxelize voxelize = new Voxelize(this.cellHeight, this.cellSize, this.walkableClimb, this.walkableHeight, this.maxSlope);
     voxelize.inputExtraMeshes = inputExtraMeshes;
     voxelize.maxEdgeLength = this.maxEdgeLength;
     int num5 = -1;
     Stopwatch stopwatch = Stopwatch.StartNew();
     for (int k = 0; k < num4; k++)
     {
         for (int l = 0; l < num3; l++)
         {
             int num6 = k * this.tileXCount + l;
             Console.WriteLine(string.Concat(new object[]
             {
                 "Generating Tile #",
                 num6,
                 " of ",
                 num4 * num3
             }));
             if (statusCallback != null && (num6 * 10 / this.tiles.Length > num5 || stopwatch.ElapsedMilliseconds > 2000L))
             {
                 num5 = num6 * 10 / this.tiles.Length;
                 stopwatch.Reset();
                 stopwatch.Start();
                 statusCallback(new Progress(AstarMath.MapToRange(0.1f, 0.9f, (float)num6 / (float)this.tiles.Length), string.Concat(new object[]
                 {
                     "Building Tile ",
                     num6,
                     "/",
                     this.tiles.Length
                 })));
             }
             this.BuildTileMesh(voxelize, l, k);
         }
     }
     Console.WriteLine("Assigning Graph Indices");
     if (statusCallback != null)
     {
         statusCallback(new Progress(0.9f, "Connecting tiles"));
     }
     uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex(this);
     GraphNodeDelegateCancelable del = delegate(GraphNode n)
     {
         n.GraphIndex = graphIndex;
         return true;
     };
     this.GetNodes(del);
     for (int m = 0; m < num4; m++)
     {
         for (int n2 = 0; n2 < num3; n2++)
         {
             Console.WriteLine(string.Concat(new object[]
             {
                 "Connecing Tile #",
                 m * this.tileXCount + n2,
                 " of ",
                 num4 * num3
             }));
             if (n2 < num3 - 1)
             {
                 this.ConnectTiles(this.tiles[n2 + m * this.tileXCount], this.tiles[n2 + 1 + m * this.tileXCount]);
             }
             if (m < num4 - 1)
             {
                 this.ConnectTiles(this.tiles[n2 + m * this.tileXCount], this.tiles[n2 + (m + 1) * this.tileXCount]);
             }
         }
     }
 }
Beispiel #18
0
 // Token: 0x06000526 RID: 1318 RVA: 0x0002CF88 File Offset: 0x0002B388
 public override void ScanInternal(OnScanStatus statusCallback)
 {
     if (this.root == null)
     {
         GameObject[] array = GameObject.FindGameObjectsWithTag(this.searchTag);
         if (array == null)
         {
             this.nodes     = new PointNode[0];
             this.nodeCount = 0;
             return;
         }
         this.nodes     = new PointNode[array.Length];
         this.nodeCount = this.nodes.Length;
         for (int i = 0; i < this.nodes.Length; i++)
         {
             this.nodes[i] = new PointNode(this.active);
         }
         for (int j = 0; j < array.Length; j++)
         {
             this.nodes[j].SetPosition((Int3)array[j].transform.position);
             this.nodes[j].Walkable   = true;
             this.nodes[j].gameObject = array[j].gameObject;
         }
     }
     else if (!this.recursive)
     {
         this.nodes     = new PointNode[this.root.childCount];
         this.nodeCount = this.nodes.Length;
         for (int k = 0; k < this.nodes.Length; k++)
         {
             this.nodes[k] = new PointNode(this.active);
         }
         int         num        = 0;
         IEnumerator enumerator = this.root.GetEnumerator();
         try
         {
             while (enumerator.MoveNext())
             {
                 object    obj       = enumerator.Current;
                 Transform transform = (Transform)obj;
                 this.nodes[num].SetPosition((Int3)transform.position);
                 this.nodes[num].Walkable   = true;
                 this.nodes[num].gameObject = transform.gameObject;
                 num++;
             }
         }
         finally
         {
             IDisposable disposable;
             if ((disposable = (enumerator as IDisposable)) != null)
             {
                 disposable.Dispose();
             }
         }
     }
     else
     {
         this.nodes     = new PointNode[PointGraph.CountChildren(this.root)];
         this.nodeCount = this.nodes.Length;
         for (int l = 0; l < this.nodes.Length; l++)
         {
             this.nodes[l] = new PointNode(this.active);
         }
         int num2 = 0;
         this.AddChildren(ref num2, this.root);
     }
     if (this.optimizeForSparseGraph)
     {
         this.RebuildNodeLookup();
     }
     if (this.maxDistance >= 0f)
     {
         List <PointNode> list  = new List <PointNode>(3);
         List <uint>      list2 = new List <uint>(3);
         for (int m = 0; m < this.nodes.Length; m++)
         {
             list.Clear();
             list2.Clear();
             PointNode pointNode = this.nodes[m];
             if (this.optimizeForSparseGraph)
             {
                 Int3 lhs  = this.WorldToLookupSpace(pointNode.position);
                 int  num3 = (this.lookupCellSize.y != 0) ? PointGraph.ThreeDNeighbours.Length : 9;
                 for (int n = 0; n < num3; n++)
                 {
                     Int3      key = lhs + PointGraph.ThreeDNeighbours[n];
                     PointNode next;
                     if (this.nodeLookup.TryGetValue(key, out next))
                     {
                         while (next != null)
                         {
                             float num4 = 0f;
                             if (this.IsValidConnection(pointNode, next, out num4))
                             {
                                 list.Add(next);
                                 list2.Add((uint)Mathf.RoundToInt(num4 * 1000f));
                             }
                             next = next.next;
                         }
                     }
                 }
             }
             else
             {
                 for (int num5 = 0; num5 < this.nodes.Length; num5++)
                 {
                     if (m != num5)
                     {
                         PointNode pointNode2 = this.nodes[num5];
                         float     num6       = 0f;
                         if (this.IsValidConnection(pointNode, pointNode2, out num6))
                         {
                             list.Add(pointNode2);
                             list2.Add((uint)Mathf.RoundToInt(num6 * 1000f));
                         }
                     }
                 }
             }
             pointNode.connections     = list.ToArray();
             pointNode.connectionCosts = list2.ToArray();
         }
     }
 }
		public override void ScanInternal (OnScanStatus statusCallback) {
			
			AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}

#if !ASTAR_JPS
			if (this.useJumpPointSearch) {
				Debug.LogError ("Trying to use Jump Point Search, but support for it is not enabled. Please enable it in the inspector (Grid Graph settings).");
			}
#endif
			
			SetUpOffsetsAndCosts ();
			
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);
			GridNode.SetGridGraph (graphIndex,this);

			nodes = new GridNode[width*depth];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			textureData.Initialize ();
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					GridNode node = nodes[z*width+x];
					
					node.NodeInGridIndex = z*width+x;
					
					UpdateNodePositionCollision (node,x,z);
					
					textureData.Apply (node,x,z);
				}
			}
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
				
					GridNode node = nodes[z*width+x];
						
					CalculateConnections (nodes,x,z,node);
					
#if ASTARDEBUG
					if (z == 5 && x == 5) {
						int index = z*width+x;
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white);
					}
#endif
				}
			}
			
			
			ErodeWalkableArea ();
		}
Beispiel #20
0
		public override void ScanInternal (OnScanStatus statusCallback) {
			
			AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}
			
			//GenerateBounds ();
			
			/*neighbourOffsets = new int[8] {
				-width-1,-width,-width+1,
				-1,1,
				width-1,width,width+1
			}*/
			
			SetUpOffsetsAndCosts ();
			
			//GridNode.RemoveGridGraph (this);
			
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);
			GridNode.SetGridGraph (graphIndex,this);
			
			//graphNodes = new GridNode[width*depth];
			
			//nodes = CreateNodes (width*depth);
			nodes = new GridNode[width*depth];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			textureData.Initialize ();
			
			//Max slope in cosinus
			//float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					GridNode node = nodes[z*width+x];//new GridNode ();
					
					node.NodeInGridIndex = z*width+x;
					
					UpdateNodePositionCollision (node,x,z);
					
					textureData.Apply (node,x,z);
					
					/*node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));
					
					RaycastHit hit;
					
					bool walkable = true;
					
					node.position = collision.CheckHeight (node.position, out hit, out walkable);
					
					node.penalty = 0;//Mathf.RoundToInt (Random.value*100);
					
					//Check if the node is on a slope steeper than permitted
					if (walkable && useRaycastNormal && collision.heightCheck) {
						
						if (hit.normal != Vector3.zero) {
							//Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle)
							float angle = Vector3.Dot (hit.normal.normalized,Vector3.up);
							
							if (angle < cosAngle) {
								walkable = false;
							}
						}
					}
					
					//If the walkable flag has already been set to false, there is no point in checking for it again
					if (walkable) {
						node.walkable = collision.Check (node.position);
					} else {
						node.walkable = walkable;
					}*/
					
				}
			}
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
				
					GridNode node = nodes[z*width+x];
						
					CalculateConnections (nodes,x,z,node);
					
#if ASTARDEBUG
					if (z == 5 && x == 5) {
						int index = z*width+x;
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black);
						Debug.DrawRay ((Vector3)node.position,(Vector3)(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white);
					}
#endif
				}
			}
			
			
			ErodeWalkableArea ();
			//Assign the nodes to the main storage
			
			//startIndex = AstarPath.active.AssignNodes (graphNodes);
			//endIndex = startIndex+graphNodes.Length;
		}
        public override void ScanInternal(OnScanStatus statusCallback) {
            var walkableOpenSpaceWaypoints = GenerateWalkableOpenSpaceWaypoints();
            var walkableSystemWaypoints = GenerateWalkableInteriorSystemWaypoints();

            int nextNodeIndex = Constants.Zero;
            AddNodes(walkableOpenSpaceWaypoints, Topography.OpenSpace.AStarTagValue(), ref nextNodeIndex);  // OpenSpaceTagMask
            AddNodes(walkableSystemWaypoints, Topography.System.AStarTagValue(), ref nextNodeIndex);    // SystemTagMask

            MakeConnections();
        }
		public override void ScanInternal (OnScanStatus status) {
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}
			
			//GenerateBounds ();
			
			/*neighbourOffsets = new int[8] {
				-width-1,-width,-width+1,
				-1,1,
				width-1,width,width+1
			}*/
			
			SetUpOffsetsAndCosts ();
			
			//GridNode.RemoveGridGraph (this);
			
			LevelGridNode.SetGridGraph (active.astarData.GetGraphIndex(this), this);
			
			//graphNodes = new LevelGridNode[width*depth];
			
			//nodes = CreateNodes (width*depth);
			//graphNodes = nodes as LevelGridNode[];
			
			maxClimb = Mathf.Clamp (maxClimb,0,characterHeight);
			
			LinkedLevelCell[] linkedCells = new LinkedLevelCell[width*depth];
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					linkedCells[z*width+x] = new LinkedLevelCell ();
					
					LinkedLevelCell llc = linkedCells[z*width+x];
					//GridNode node = graphNodes[z*width+x];//new LevelGridNode ();
					
					//node.SetIndex (z*width+x);
					
					Vector3 pos = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));
					
					
					RaycastHit[] hits = collision.CheckHeightAll (pos);
					
					//Sort the hits based on distance with bubble sort (fast enough)
					//Furthest away first (i.e lowest nodes in the graph)
					/*bool changed = true;
					while (changed) {
						changed = false;
						for (int i=0;i<hits.Length-1;i++) {
							if (hits[i].distance < hits[i+1].distance) {
								RaycastHit tmp = hits[i];
								hits[i] = hits[i+1];
								hits[i+1] = tmp;
								changed = true;
							}
						}
					}*/
					
					for (int i=0;i<hits.Length/2;i++) {
						RaycastHit tmp = hits[i];
						
						hits[i] = hits[hits.Length-1-i];
						hits[hits.Length-1-i] = tmp;
					}
					
					if (hits.Length > 0) {
						
						//lln.position = hits[0].point;
						//lln.walkable = collision.Check (lln.position);
						
						
						/*LinkedLevelNode lln = new LinkedLevelNode ();
						lln.position = hits[0].point;
						lln.walkable = collision.Check (lln.position);
						llc.first = lln;*/
						
						LinkedLevelNode lln = null;
						
						for (int i=0;i<hits.Length;i++) {
							
							LinkedLevelNode tmp = new LinkedLevelNode ();
							tmp.position = hits[i].point;
							
							if (lln != null) {
								/** \todo Use hit.distance instead */
								if (tmp.position.y - lln.position.y <= mergeSpanRange) {
									//if (tmp.position.y > lln.position.y) {
										lln.position = tmp.position;
										lln.hit = hits[i];
										lln.walkable = collision.Check (tmp.position);
									//}
									continue;
								}
							}
							
							tmp.walkable = collision.Check (tmp.position);
							tmp.hit = hits[i];
							tmp.height = float.PositiveInfinity;
							
							if (llc.first == null) {
								llc.first = tmp;
								lln = tmp;
							} else {
								lln.next = tmp;
								
								lln.height = tmp.position.y - lln.position.y;
								lln = lln.next;
							}
						
						}
					} else {
						LinkedLevelNode lln = new LinkedLevelNode ();
						lln.position = pos;
						lln.height = float.PositiveInfinity;
						lln.walkable = !collision.unwalkableWhenNoGround;
						llc.first = lln;
					}
					
					//node.penalty = 0;//Mathf.RoundToInt (Random.value*100);
					
					//node.walkable = collision.Check (node.position);
					
					//node.SetGridIndex (gridIndex);
				}
			}
			
			
			int spanCount = 0;
			layerCount = 0;
			//Count the total number of nodes in the graph
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					LinkedLevelCell llc = linkedCells[z*width+x];
					
					LinkedLevelNode lln = llc.first;
					int cellCount = 0;
					//Loop through all nodes in this cell
					do {
						cellCount++;
						spanCount++;
						lln = lln.next;
					} while (lln != null);
					
					layerCount = cellCount > layerCount ? cellCount : layerCount;
				}
			}
			
			if (layerCount > LevelGridNode.MaxLayerCount) {
				Debug.LogError ("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found "+layerCount+")");
				return;
			}
			
			//Create all nodes
			nodes = new LevelGridNode[width*depth*layerCount];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new LevelGridNode (active);
				nodes[i].Penalty = initialPenalty;
			}
			
			int nodeIndex = 0;
			
			//Max slope in cosinus
			float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);
			
			for (int z = 0; z < depth; z++) {
				for (int x = 0; x < width; x++) {
					
					LinkedLevelCell llc = linkedCells[z*width+x];
					LinkedLevelNode lln = llc.first;
					
					llc.index = nodeIndex;
					
					int count = 0;
					int layerIndex = 0;
					do {
						LevelGridNode node = nodes[z*width+x + width*depth*layerIndex] as LevelGridNode;
#if ASTAR_SET_LEVELGRIDNODE_HEIGHT
						node.height = lln.height;
#endif
						node.SetPosition ((Int3)lln.position);
						node.Walkable = lln.walkable;
						
						//Adjust penalty based on the surface slope
						if (lln.hit.normal != Vector3.zero && (penaltyAngle || cosAngle < 1.0f)) {
							//Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle)
							float angle = Vector3.Dot (lln.hit.normal.normalized,collision.up);
							
							//Add penalty based on normal
							if (penaltyAngle) {
								node.Penalty += (uint)Mathf.RoundToInt ((1F-angle)*penaltyAngleFactor);
							}
							
							//Check if the slope is flat enough to stand on
							if (angle < cosAngle) {
								node.Walkable = false;
							}
						}
						
						node.NodeInGridIndex = z*width+x;
						//node.nodeOffset = count;
						if (lln.height < characterHeight) {
							node.Walkable = false;
						}
						
						node.WalkableErosion = node.Walkable;
						
						nodeIndex++;
						count++;
						lln = lln.next;
						layerIndex++;
					} while (lln != null);
					
					for (;layerIndex<layerCount;layerIndex++) {
						nodes[z*width+x + width*depth*layerIndex] = null;
					}
					
					llc.count = count;
				}
			}
			
			nodeIndex = 0;
			
			nodeCellIndices = new int[linkedCells.Length];
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					/*LinkedLevelCell llc = linkedCells[z*width+x];
					LinkedLevelNode lln = llc.first;
					
					nodeCellIndices[z*width+x] = llc.index;
					
					do {
						LevelGridNode node = (LevelGridNode)nodes[nodeIndex];
						
						CalculateConnections (nodes,linkedCells,node,x,z,n);
						nodeIndex++;
						lln = lln.next;
					} while (lln != null);*/
					
					for (int i=0;i<layerCount;i++) {
						GraphNode node = nodes[z*width+x + width*depth*i];
						CalculateConnections (nodes,node,x,z,i);
					}
				}
			}
			
			uint graphIndex = (uint)active.astarData.GetGraphIndex(this);
			
			for (int i=0;i<nodes.Length;i++) {
				LevelGridNode lgn = nodes[i] as LevelGridNode;
				if (lgn == null) continue;
				
				UpdatePenalty (lgn);
				
				lgn.GraphIndex = graphIndex;
				
				//Set the node to be unwalkable if it hasn't got any connections
				if (!lgn.HasAnyGridConnections ()) {
					lgn.Walkable = false;
					lgn.WalkableErosion = lgn.Walkable;
				}
			}
					/*GridNode node = graphNodes[z*width+x];
				
					CalculateConnections (graphNodes,x,z,node);
					
					if (z == 5 && x == 5) {
						int index = z*width+x;
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white);
					}*/
				//}
			//}
			
			ErodeWalkableArea (0,0,width,depth);
		}
        public override void ScanInternal(OnScanStatus statusCallback)
        {
            if (root == null)
            {
                //If there is no root object, try to find nodes with the specified tag instead
                GameObject[] gos = GameObject.FindGameObjectsWithTag(searchTag);
                nodeGameObjects = gos;

                if (gos == null)
                {
                    nodes     = new PointNode[0];
                    nodeCount = 0;
                    return;
                }

                //Create and set up the found nodes
                nodes     = new PointNode[gos.Length];
                nodeCount = nodes.Length;

                for (int i = 0; i < nodes.Length; i++)
                {
                    nodes[i] = new PointNode(active);
                }

                //CreateNodes (gos.Length);
                for (int i = 0; i < gos.Length; i++)
                {
                    (nodes[i] as PointNode).SetPosition((Int3)gos[i].transform.position);
                    nodes[i].Walkable = true;

#if !AstarRelease && FALSE
                    NodeObject nobj = gos[i].GetComponent <NodeObject>();
                    if (nobj != null)
                    {
                        nodes[i].Walkable = nobj.walkable;
                    }
#endif
                }
            }
            else
            {
                //Search the root for children and create nodes for them
                if (!recursive)
                {
                    nodes     = new PointNode[root.childCount];
                    nodeCount = nodes.Length;

                    for (int i = 0; i < nodes.Length; i++)
                    {
                        nodes[i] = new PointNode(active);
                    }

                    nodeGameObjects = new GameObject[nodes.Length];

                    int c = 0;
                    foreach (Transform child in root)
                    {
                        (nodes[c] as PointNode).SetPosition((Int3)child.position);
                        nodes[c].Walkable = true;

                        nodeGameObjects[c] = child.gameObject;

#if !AstarRelease && FALSE
                        NodeObject nobj = child.GetComponent <NodeObject>();
                        if (nobj != null)
                        {
                            nodes[c].Walkable = nobj.walkable;
                        }
#endif

                        c++;
                    }
                }
                else
                {
                    nodes     = new PointNode[CountChildren(root)];
                    nodeCount = nodes.Length;

                    for (int i = 0; i < nodes.Length; i++)
                    {
                        nodes[i] = new PointNode(active);
                    }
                    //CreateNodes (CountChildren (root));
                    nodeGameObjects = new GameObject[nodes.Length];

                    int startID = 0;
                    AddChildren(ref startID, root);
                }
            }

            if (optimizeForSparseGraph)
            {
                RebuildNodeLookup();
            }

            if (maxDistance >= 0)
            {
                //To avoid too many allocations, these lists are reused for each node
                List <PointNode> connections = new List <PointNode>(3);
                List <uint>      costs       = new List <uint>(3);

                //Loop through all nodes and add connections to other nodes
                for (int i = 0; i < nodes.Length; i++)
                {
                    connections.Clear();
                    costs.Clear();

                    PointNode node = nodes[i];


                    if (optimizeForSparseGraph)
                    {
                        Int3 p = WorldToLookupSpace(node.position);

                        int l = lookupCellSize.y == 0 ? 9 : ThreeDNeighbours.Length;

                        for (int j = 0; j < l; j++)
                        {
                            Int3 np = p + ThreeDNeighbours[j];

                            PointNode other;
                            if (nodeLookup.TryGetValue(np, out other))
                            {
                                while (other != null)
                                {
                                    float dist = 0;
                                    if (IsValidConnection(node, other, out dist))
                                    {
                                        connections.Add(other);
                                        /** \todo Is this equal to .costMagnitude */
                                        costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision));
                                    }

                                    other = other.next;
                                }
                            }
                        }
                    }
                    else
                    {
                        // Only brute force is available in the free version
                        for (int j = 0; j < nodes.Length; j++)
                        {
                            if (i == j)
                            {
                                continue;
                            }

                            PointNode other = nodes[j];

                            float dist = 0;
                            if (IsValidConnection(node, other, out dist))
                            {
                                connections.Add(other);
                                /** \todo Is this equal to .costMagnitude */
                                costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision));
                            }
                        }
                    }
                    node.connections     = connections.ToArray();
                    node.connectionCosts = costs.ToArray();
                }
            }

            //GC can clear this up now.
            nodeGameObjects = null;
        }
Beispiel #24
0
        public override void ScanInternal(OnScanStatus status)
        {
            this.scans++;
            if (this.nodeSize <= 0f)
            {
                return;
            }
            base.GenerateMatrix();
            if (this.width > 1024 || this.depth > 1024)
            {
                Debug.LogError("One of the grid's sides is longer than 1024 nodes");
                return;
            }
            this.lastScannedWidth = this.width;
            this.lastScannedDepth = this.depth;
            this.SetUpOffsetsAndCosts();
            LevelGridNode.SetGridGraph(this.active.astarData.GetGraphIndex(this), this);
            this.maxClimb = Mathf.Clamp(this.maxClimb, 0f, this.characterHeight);
            LinkedLevelCell[] array = new LinkedLevelCell[this.width * this.depth];
            if (this.collision == null)
            {
                this.collision = new GraphCollision();
            }
            this.collision.Initialize(this.matrix, this.nodeSize);
            for (int i = 0; i < this.depth; i++)
            {
                for (int j = 0; j < this.width; j++)
                {
                    array[i * this.width + j] = new LinkedLevelCell();
                    LinkedLevelCell linkedLevelCell = array[i * this.width + j];
                    Vector3         position        = this.matrix.MultiplyPoint3x4(new Vector3((float)j + 0.5f, 0f, (float)i + 0.5f));
                    RaycastHit[]    array2          = this.collision.CheckHeightAll(position);
                    for (int k = 0; k < array2.Length / 2; k++)
                    {
                        RaycastHit raycastHit = array2[k];
                        array2[k] = array2[array2.Length - 1 - k];
                        array2[array2.Length - 1 - k] = raycastHit;
                    }
                    if (array2.Length > 0)
                    {
                        LinkedLevelNode linkedLevelNode = null;
                        for (int l = 0; l < array2.Length; l++)
                        {
                            LinkedLevelNode linkedLevelNode2 = new LinkedLevelNode();
                            linkedLevelNode2.position = array2[l].point;
                            if (linkedLevelNode != null && linkedLevelNode2.position.y - linkedLevelNode.position.y <= this.mergeSpanRange)
                            {
                                linkedLevelNode.position = linkedLevelNode2.position;
                                linkedLevelNode.hit      = array2[l];
                                linkedLevelNode.walkable = this.collision.Check(linkedLevelNode2.position);
                            }
                            else
                            {
                                linkedLevelNode2.walkable = this.collision.Check(linkedLevelNode2.position);
                                linkedLevelNode2.hit      = array2[l];
                                linkedLevelNode2.height   = float.PositiveInfinity;
                                if (linkedLevelCell.first == null)
                                {
                                    linkedLevelCell.first = linkedLevelNode2;
                                    linkedLevelNode       = linkedLevelNode2;
                                }
                                else
                                {
                                    linkedLevelNode.next   = linkedLevelNode2;
                                    linkedLevelNode.height = linkedLevelNode2.position.y - linkedLevelNode.position.y;
                                    linkedLevelNode        = linkedLevelNode.next;
                                }
                            }
                        }
                    }
                    else
                    {
                        linkedLevelCell.first = new LinkedLevelNode
                        {
                            position = position,
                            height   = float.PositiveInfinity,
                            walkable = !this.collision.unwalkableWhenNoGround
                        };
                    }
                }
            }
            int num = 0;

            this.layerCount = 0;
            for (int m = 0; m < this.depth; m++)
            {
                for (int n = 0; n < this.width; n++)
                {
                    LinkedLevelCell linkedLevelCell2 = array[m * this.width + n];
                    LinkedLevelNode linkedLevelNode3 = linkedLevelCell2.first;
                    int             num2             = 0;
                    do
                    {
                        num2++;
                        num++;
                        linkedLevelNode3 = linkedLevelNode3.next;
                    }while (linkedLevelNode3 != null);
                    this.layerCount = ((num2 <= this.layerCount) ? this.layerCount : num2);
                }
            }
            if (this.layerCount > 255)
            {
                Debug.LogError("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found " + this.layerCount + ")");
                return;
            }
            this.nodes = new LevelGridNode[this.width * this.depth * this.layerCount];
            for (int num3 = 0; num3 < this.nodes.Length; num3++)
            {
                this.nodes[num3]         = new LevelGridNode(this.active);
                this.nodes[num3].Penalty = this.initialPenalty;
            }
            int   num4 = 0;
            float num5 = Mathf.Cos(this.maxSlope * 0.0174532924f);

            for (int num6 = 0; num6 < this.depth; num6++)
            {
                for (int num7 = 0; num7 < this.width; num7++)
                {
                    LinkedLevelCell linkedLevelCell3 = array[num6 * this.width + num7];
                    LinkedLevelNode linkedLevelNode4 = linkedLevelCell3.first;
                    linkedLevelCell3.index = num4;
                    int num8 = 0;
                    int num9 = 0;
                    do
                    {
                        LevelGridNode levelGridNode = this.nodes[num6 * this.width + num7 + this.width * this.depth * num9];
                        levelGridNode.SetPosition((Int3)linkedLevelNode4.position);
                        levelGridNode.Walkable = linkedLevelNode4.walkable;
                        if (linkedLevelNode4.hit.normal != Vector3.zero && (this.penaltyAngle || num5 < 1f))
                        {
                            float num10 = Vector3.Dot(linkedLevelNode4.hit.normal.normalized, this.collision.up);
                            if (this.penaltyAngle)
                            {
                                levelGridNode.Penalty += (uint)Mathf.RoundToInt((1f - num10) * this.penaltyAngleFactor);
                            }
                            if (num10 < num5)
                            {
                                levelGridNode.Walkable = false;
                            }
                        }
                        levelGridNode.NodeInGridIndex = num6 * this.width + num7;
                        if (linkedLevelNode4.height < this.characterHeight)
                        {
                            levelGridNode.Walkable = false;
                        }
                        levelGridNode.WalkableErosion = levelGridNode.Walkable;
                        num4++;
                        num8++;
                        linkedLevelNode4 = linkedLevelNode4.next;
                        num9++;
                    }while (linkedLevelNode4 != null);
                    while (num9 < this.layerCount)
                    {
                        this.nodes[num6 * this.width + num7 + this.width * this.depth * num9] = null;
                        num9++;
                    }
                    linkedLevelCell3.count = num8;
                }
            }
            this.nodeCellIndices = new int[array.Length];
            for (int num11 = 0; num11 < this.depth; num11++)
            {
                for (int num12 = 0; num12 < this.width; num12++)
                {
                    for (int num13 = 0; num13 < this.layerCount; num13++)
                    {
                        GraphNode node = this.nodes[num11 * this.width + num12 + this.width * this.depth * num13];
                        this.CalculateConnections(this.nodes, node, num12, num11, num13);
                    }
                }
            }
            uint graphIndex = (uint)this.active.astarData.GetGraphIndex(this);

            for (int num14 = 0; num14 < this.nodes.Length; num14++)
            {
                LevelGridNode levelGridNode2 = this.nodes[num14];
                if (levelGridNode2 != null)
                {
                    this.UpdatePenalty(levelGridNode2);
                    levelGridNode2.GraphIndex = graphIndex;
                    if (!levelGridNode2.HasAnyGridConnections())
                    {
                        levelGridNode2.Walkable        = false;
                        levelGridNode2.WalkableErosion = levelGridNode2.Walkable;
                    }
                }
            }
            this.ErodeWalkableArea(0, 0, this.width, this.depth);
        }
Beispiel #25
0
 public override void ScanInternal(OnScanStatus statusCallback)
 {
     TriangleMeshNode.SetNavmeshHolder(AstarPath.active.astarData.GetGraphIndex(this), this);
     this.ScanTiledNavmesh(statusCallback);
 }
Beispiel #26
0
        public override void ScanInternal(OnScanStatus statusCallback)
        {
            if (root == null)
            {
                //If there is no root object, try to find nodes with the specified tag instead
                GameObject[] gos = searchTag != null?GameObject.FindGameObjectsWithTag(searchTag) : null;

                if (gos == null)
                {
                    nodes     = new PointNode[0];
                    nodeCount = 0;
                    return;
                }

                //Create and set up the found nodes
                nodes     = new PointNode[gos.Length];
                nodeCount = nodes.Length;

                for (int i = 0; i < nodes.Length; i++)
                {
                    nodes[i] = new PointNode(active);
                }

                for (int i = 0; i < gos.Length; i++)
                {
                    nodes[i].SetPosition((Int3)gos[i].transform.position);
                    nodes[i].Walkable   = true;
                    nodes[i].gameObject = gos[i].gameObject;
                }
            }
            else
            {
                //Search the root for children and create nodes for them
                if (!recursive)
                {
                    nodes     = new PointNode[root.childCount];
                    nodeCount = nodes.Length;

                    for (int i = 0; i < nodes.Length; i++)
                    {
                        nodes[i] = new PointNode(active);
                    }

                    int c = 0;
                    foreach (Transform child in root)
                    {
                        nodes[c].SetPosition((Int3)child.position);
                        nodes[c].Walkable   = true;
                        nodes[c].gameObject = child.gameObject;

                        c++;
                    }
                }
                else
                {
                    nodes     = new PointNode[CountChildren(root)];
                    nodeCount = nodes.Length;

                    for (int i = 0; i < nodes.Length; i++)
                    {
                        nodes[i] = new PointNode(active);
                    }
                    //CreateNodes (CountChildren (root));

                    int startID = 0;
                    AddChildren(ref startID, root);
                }
            }


            if (maxDistance >= 0)
            {
                //To avoid too many allocations, these lists are reused for each node
                var connections = new List <PointNode>(3);
                var costs       = new List <uint>(3);

                //Loop through all nodes and add connections to other nodes
                for (int i = 0; i < nodes.Length; i++)
                {
                    connections.Clear();
                    costs.Clear();

                    PointNode node = nodes[i];

                    // Only brute force is available in the free version
                    for (int j = 0; j < nodes.Length; j++)
                    {
                        if (i == j)
                        {
                            continue;
                        }

                        PointNode other = nodes[j];

                        float dist;
                        if (IsValidConnection(node, other, out dist))
                        {
                            connections.Add(other);
                            /** \todo Is this equal to .costMagnitude */
                            costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision));
                        }
                    }
                    node.connections     = connections.ToArray();
                    node.connectionCosts = costs.ToArray();
                }
            }
        }
Beispiel #27
0
		public override void ScanInternal (OnScanStatus statusCallback) {
			AstarProfiler.Reset ();
			AstarProfiler.StartProfile ("Base Scan");
			//AstarProfiler.InitializeFastProfile (new string[] {"Rasterize", "Rasterize Inner 1", "Rasterize Inner 2", "Rasterize Inner 3"});
			
			TriangleMeshNode.SetNavmeshHolder (AstarPath.active.astarData.GetGraphIndex (this), this);
			
			
			ScanTiledNavmesh (statusCallback);
			
			
#if DEBUG_REPLAY
			DebugReplay.WriteToFile ();
#endif
			AstarProfiler.PrintFastResults();
		}
        // Scan() has been deprecated, replaced by ScanInternal. 
        public override void ScanInternal(OnScanStatus statusCallback) {
            // ********************************************************************
            // NOTE: removed all code that derived nodes from GameObjects and Tags
            // ********************************************************************

            //D.Log("ScanInternal called.");
            var walkableOpenSpaceWaypoints = GetWalkableOpenSpaceWaypoints();
            var unwalkableOpenSpaceWaypoints = GetUnWalkableOpenSpaceWaypoints();
            var walkableSystemWaypoints = GetWalkableInteriorSystemWaypoints();

            int waypointCount = walkableOpenSpaceWaypoints.Count + unwalkableOpenSpaceWaypoints.Count + walkableSystemWaypoints.Count;

            // Make the Nodes array
            nodes = new PointNode[waypointCount];
            nodeCount = waypointCount;
            //for (int nodeIndex = 0; nodeIndex < waypointCount; nodeIndex++) {
            //    nodes[nodeIndex] = new PointNode(active);
            //}

            int nextNodeIndex = Constants.Zero;
            bool isWalkable = true;
            PopulateNodes(walkableOpenSpaceWaypoints, openSpaceTagMask, isWalkable, ref nextNodeIndex);
            //D.Log("NextNodeIndex = {0}.", nextNodeIndex);
            PopulateNodes(walkableSystemWaypoints, systemTagMask, isWalkable, ref nextNodeIndex);
            //D.Log("NextNodeIndex = {0}.", nextNodeIndex);

            isWalkable = false;
            PopulateNodes(unwalkableOpenSpaceWaypoints, openSpaceTagMask, isWalkable, ref nextNodeIndex);
            //D.Log("NextNodeIndex = {0}.", nextNodeIndex);

            D.Log("{0} Pathfinding nodes.", nodeCount);

            if (maxDistance >= 0) {
                //To avoid too many allocations, these lists are reused for each node
                List<PointNode> connections = new List<PointNode>(3);
                List<uint> costs = new List<uint>(3);

                //Loop through all nodes and add connections to other nodes
                int connectionCount = 0;
                int invalidConnectionCount = 0;
                for (int i = 0; i < nodes.Length; i++) {
                    connections.Clear();
                    costs.Clear();

                    PointNode node = nodes[i];

                    // OPTIMIZE Only brute force is available in the free version
                    for (int j = 0; j < nodes.Length; j++) {
                        if (i == j) { continue; }

                        PointNode other = nodes[j];

                        float dist = 0;
                        if (IsValidConnection(node, other, out dist)) {
                            connections.Add(other);
                            /** \todo Is this equal to .costMagnitude */
                            costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision));
                        }
                        else {
                            invalidConnectionCount++;
                        }
                        //else if (dist <= maxDistance) { // maxDistance is currently 700
                        //    invalidConnectionCount++;
                        //    D.Warn("Connection from Node at {0} to Node at {1} is invalid.", (Vector3)node.position, (Vector3)other.position);
                        //    D.AssertException(false);
                        //}
                    }
                    node.connections = connections.ToArray();
                    connectionCount += connections.Count;
                    node.connectionCosts = costs.ToArray();
                }
                int totalConnectionsAttempted = connectionCount + invalidConnectionCount;
                D.Log("{0}/{1} valid connections.", connectionCount, totalConnectionsAttempted);
            }
        }
Beispiel #29
0
        protected void ScanAllTiles(OnScanStatus statusCallback)
        {
#if ASTARDEBUG
            System.Console.WriteLine("Recast Graph -- Collecting Meshes");
#endif

#if BNICKSON_UPDATED
            editorTileSize = (int)(EditorVars.GridSize / cellSize);
#endif

            //----

            //Voxel grid size
            int gw = (int)(forcedBounds.size.x / cellSize + 0.5f);
            int gd = (int)(forcedBounds.size.z / cellSize + 0.5f);

            if (!useTiles)
            {
                tileSizeX = gw;
                tileSizeZ = gd;
            }
            else
            {
                tileSizeX = editorTileSize;
                tileSizeZ = editorTileSize;
            }

            //Number of tiles
            int tw = (gw + tileSizeX - 1) / tileSizeX;
            int td = (gd + tileSizeZ - 1) / tileSizeZ;

            tileXCount = tw;
            tileZCount = td;

            if (tileXCount * tileZCount > TileIndexMask + 1)
            {
                throw new System.Exception("Too many tiles (" + (tileXCount * tileZCount) + ") maximum is " + (TileIndexMask + 1) +
                                           "\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector.");
            }

            tiles = new NavmeshTile[tileXCount * tileZCount];

#if ASTARDEBUG
            System.Console.WriteLine("Recast Graph -- Creating Voxel Base");
#endif

            // If this is true, just fill the graph with empty tiles
            if (scanEmptyGraph)
            {
                for (int z = 0; z < td; z++)
                {
                    for (int x = 0; x < tw; x++)
                    {
                        tiles[z * tileXCount + x] = NewEmptyTile(x, z);
                    }
                }
                return;
            }

            AstarProfiler.StartProfile("Finding Meshes");
            List <ExtraMesh> extraMeshes;

#if !NETFX_CORE || UNITY_EDITOR
            System.Console.WriteLine("Collecting Meshes");
#endif
            CollectMeshes(out extraMeshes, forcedBounds);

            AstarProfiler.EndProfile("Finding Meshes");

            // A walkableClimb higher than walkableHeight can cause issues when generating the navmesh since then it can in some cases
            // Both be valid for a character to walk under an obstacle and climb up on top of it (and that cannot be handled with navmesh without links)
            // The editor scripts also enforce this but we enforce it here too just to be sure
            walkableClimb = Mathf.Min(walkableClimb, walkableHeight);

            //Create the voxelizer and set all settings
            var vox = new Voxelize(cellHeight, cellSize, walkableClimb, walkableHeight, maxSlope);
            vox.inputExtraMeshes = extraMeshes;

            vox.maxEdgeLength = maxEdgeLength;

            int lastInfoCallback = -1;
            var watch            = System.Diagnostics.Stopwatch.StartNew();

            //Generate all tiles
            for (int z = 0; z < td; z++)
            {
                for (int x = 0; x < tw; x++)
                {
                    int tileNum = z * tileXCount + x;
#if !NETFX_CORE || UNITY_EDITOR
                    System.Console.WriteLine("Generating Tile #" + (tileNum) + " of " + td * tw);
#endif

                    //Call statusCallback only 10 times since it is very slow in the editor
                    if (statusCallback != null && (tileNum * 10 / tiles.Length > lastInfoCallback || watch.ElapsedMilliseconds > 2000))
                    {
                        lastInfoCallback = tileNum * 10 / tiles.Length;
                        watch.Reset();
                        watch.Start();

                        statusCallback(new Progress(Mathf.Lerp(0.1f, 0.9f, tileNum / (float)tiles.Length), "Building Tile " + tileNum + "/" + tiles.Length));
                    }

                    BuildTileMesh(vox, x, z);
                }
            }

#if !NETFX_CORE
            System.Console.WriteLine("Assigning Graph Indices");
#endif

            if (statusCallback != null)
            {
                statusCallback(new Progress(0.9f, "Connecting tiles"));
            }

            //Assign graph index to nodes
            uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex(this);

            GraphNodeDelegateCancelable del = delegate(GraphNode n) {
                n.GraphIndex = graphIndex;
                return(true);
            };
            GetNodes(del);

#if BNICKSON_UPDATED
#if DEBUG
            if (useCenterTileOnly && (3 != tileXCount || 3 != tileZCount))
            {
                EB.Debug.LogError("RecastGenerator.ScanAllTiles() : Incorrect amount of tiles generated if ceneter tile is all that is required");
            }
#endif

            int centerXTile = (tileXCount / 2);
            int centerZTile = (tileZCount / 2);
#endif

            for (int z = 0; z < td; z++)
            {
                for (int x = 0; x < tw; x++)
                {
#if BNICKSON_UPDATED
                    // if we're only using the center tile, and this is not the center tile
                    if (useCenterTileOnly && !(centerZTile == z && centerXTile == x))
                    {
                        continue;
                    }
#endif

#if !NETFX_CORE
                    System.Console.WriteLine("Connecing Tile #" + (z * tileXCount + x) + " of " + td * tw);
#endif
                    if (x < tw - 1)
                    {
                        ConnectTiles(tiles[x + z * tileXCount], tiles[x + 1 + z * tileXCount]);
                    }
                    if (z < td - 1)
                    {
                        ConnectTiles(tiles[x + z * tileXCount], tiles[x + (z + 1) * tileXCount]);
                    }
                }
            }

            AstarProfiler.PrintResults();
        }
Beispiel #30
0
	/** Scans all graphs. This is a IEnumerable, you can loop through it to get the progress
	  * \code foreach (Progress progress in AstarPath.active.ScanLoop ()) {
	*	 Debug.Log ("Scanning... " + progress.description + " - " + (progress.progress*100).ToString ("0") + "%");
	  * } \endcode
	  * \see Scan
	  */
	public void ScanLoop (OnScanStatus statusCallback) {
		
		if (graphs == null) {
			return;
		}
		
		isScanning = true;
		
		VerifyIntegrity ();

		BlockUntilPathQueueBlocked ();

		if (!Application.isPlaying) {
			GraphModifier.FindAllModifiers ();
			RelevantGraphSurface.FindAllGraphSurfaces ();
		}
		
		RelevantGraphSurface.UpdateAllPositions ();
		
		astarData.UpdateShortcuts ();
		
		//statusCallback (new Progress (0.02F,"Updating graph shortcuts"));
		
		if (statusCallback != null) statusCallback (new Progress (0.05F,"Pre processing graphs"));
		
		if (OnPreScan != null) {
			
			OnPreScan (this);
		}
		
		GraphModifier.TriggerEvent (GraphModifier.EventType.PreScan);
		
		//float startTime = Time.realtimeSinceStartup;
		System.DateTime startTime = System.DateTime.UtcNow;
		
		// Destroy previous nodes
		for (int i=0;i<graphs.Length;i++) {
			if (graphs[i] != null) {
				graphs[i].GetNodes (delegate (GraphNode node) {
					node.Destroy ();
					return true;
				});
			}
		}
		
		for (int i=0;i<graphs.Length;i++) {
			
			NavGraph graph = graphs[i];
			
			if (graph == null) {
				if (statusCallback != null) statusCallback (new Progress (AstarMath.MapTo (0.05F,0.7F,(float)(i+0.5F)/(graphs.Length+1)),"Skipping graph "+(i+1)+" of "+graphs.Length+" because it is null"));
				continue;
			}
			
			if (OnGraphPreScan != null) {
				if (statusCallback != null) statusCallback (new Progress (AstarMath.MapToRange (0.1F,0.7F,(float)(i)/(graphs.Length)),"Scanning graph "+(i+1)+" of "+graphs.Length+" - Pre processing"));
				OnGraphPreScan (graph);
			}
			
			
			
			float minp = AstarMath.MapToRange (0.1F,0.7F,(float)(i)/(graphs.Length));
			float maxp = AstarMath.MapToRange (0.1F,0.7F,(float)(i+0.95F)/(graphs.Length));
			
			if (statusCallback != null) statusCallback (new Progress (minp,"Scanning graph "+(i+1)+" of "+graphs.Length));
			
			OnScanStatus info = null;
			if (statusCallback != null) {
				info = delegate (Progress p) {
					p.progress = AstarMath.MapToRange (minp, maxp, p.progress);
					statusCallback (p);
				};
			}
			
			graph.ScanInternal (info);
			
			//statusCallback (new Progress (Mathfx.MapTo (0.05F,0.7F,(float)(i+1.9F)/(graphs.Length+1)),"Scanning graph "+(i+1)+" of "+graphs.Length+" - Assigning graph indices"));
			
			graph.GetNodes (delegate (GraphNode node) {
				node.GraphIndex = (uint)i;
				return true;
			});
			
			if (OnGraphPostScan != null) {
				if (statusCallback != null) statusCallback (new Progress (AstarMath.MapToRange (0.1F,0.7F,(float)(i+0.95F)/(graphs.Length)),"Scanning graph "+(i+1)+" of "+graphs.Length+" - Post processing"));
				OnGraphPostScan (graph);
			}
			
		}
		
		if (statusCallback != null) statusCallback (new Progress (0.8F,"Post processing graphs"));
		
		if (OnPostScan != null) {
			OnPostScan (this);
		}
		GraphModifier.TriggerEvent (GraphModifier.EventType.PostScan);
		
		ApplyLinks ();
		
		//statusCallback (new Progress (0.85F,"Applying links"));
		try {
			FlushWorkItems();
		} catch (System.Exception e) {
			Debug.LogException (e);
		}
		
		isScanning = false;
		
		
		if (statusCallback != null) statusCallback (new Progress (0.90F,"Computing areas"));
		
		FloodFill ();
		
		//statusCallback (new Progress (0.92F,"Updating misc. data"));
		
		
		VerifyIntegrity ();
		
		if (statusCallback != null) statusCallback (new Progress (0.95F,"Late post processing"));
		
		if (OnLatePostScan != null) {
			OnLatePostScan (this);
		}
		GraphModifier.TriggerEvent (GraphModifier.EventType.LatePostScan);
		
		//Perform any blocking actions and unblock (probably, some tasks might take a few frames)
		PerformBlockingActions(true);
		
		lastScanTime = (float)(System.DateTime.UtcNow-startTime).TotalSeconds;//Time.realtimeSinceStartup-startTime;
		
		System.GC.Collect ();
		
		AstarLog ("Scanning - Process took "+(lastScanTime*1000).ToString ("0")+" ms to complete");
		
	}
Beispiel #31
0
		public override void ScanInternal (OnScanStatus statusCallback) {
			
			AstarPath.OnPostScan += new OnScanDelegate (OnPostScan);
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}

			
			SetUpOffsetsAndCosts ();
			
			int graphIndex = AstarPath.active.astarData.GetGraphIndex(this);
			GridNode.SetGridGraph (graphIndex,this);

			nodes = new GridNode[width*depth];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new GridNode(active);
				nodes[i].GraphIndex = (uint)graphIndex;
			}
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					GridNode node = nodes[z*width+x];
					
					node.NodeInGridIndex = z*width+x;
					
					UpdateNodePositionCollision (node,x,z);
					
				}
			}
			
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
				
					GridNode node = nodes[z*width+x];
						
					CalculateConnections (nodes,x,z,node);
					
				}
			}
			
			
			ErodeWalkableArea ();
		}
Beispiel #32
0
 /// <summary>
 /// Scans the graph, called from <see cref="AstarPath.ScanInternal"/>
 /// Override this function to implement custom scanning logic
 /// The statusCallback may be optionally called to show progress info in the editor
 /// </summary>
 public abstract void ScanInternal(OnScanStatus statusCallback);
Beispiel #33
0
		protected void ScanAllTiles (OnScanStatus statusCallback) {

#if ASTARDEBUG
			System.Console.WriteLine ("Recast Graph -- Collecting Meshes");
#endif

			//----

			//Voxel grid size
			int gw = (int)(forcedBounds.size.x/cellSize + 0.5f);
			int gd = (int)(forcedBounds.size.z/cellSize + 0.5f);

			if (!useTiles) {
				tileSizeX = gw;
				tileSizeZ = gd;
			} else {
				tileSizeX = editorTileSize;
				tileSizeZ = editorTileSize;
			}

			//Number of tiles
			int tw = (gw + tileSizeX-1) / tileSizeX;
			int td = (gd + tileSizeZ-1) / tileSizeZ;

			tileXCount = tw;
			tileZCount = td;

			if (tileXCount * tileZCount > TileIndexMask+1) {
				throw new System.Exception ("Too many tiles ("+(tileXCount * tileZCount)+") maximum is "+(TileIndexMask+1)+
					"\nTry disabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* inspector.");
			}

			tiles = new NavmeshTile[tileXCount*tileZCount];

#if ASTARDEBUG
			System.Console.WriteLine ("Recast Graph -- Creating Voxel Base");
#endif

			// If this is true, just fill the graph with empty tiles
			if ( scanEmptyGraph ) {
				for (int z=0;z<td;z++) {
					for (int x=0;x<tw;x++) {
						tiles[z*tileXCount + x] = NewEmptyTile(x,z);
					}
				}
				return;
			}

			AstarProfiler.StartProfile ("Finding Meshes");
			List<ExtraMesh> extraMeshes;

#if !NETFX_CORE || UNITY_EDITOR
			System.Console.WriteLine ("Collecting Meshes");
#endif
			CollectMeshes (out extraMeshes, forcedBounds);

			AstarProfiler.EndProfile ("Finding Meshes");

			// A walkableClimb higher than walkableHeight can cause issues when generating the navmesh since then it can in some cases
			// Both be valid for a character to walk under an obstacle and climb up on top of it (and that cannot be handled with navmesh without links)
			// The editor scripts also enforce this but we enforce it here too just to be sure
			walkableClimb = Mathf.Min (walkableClimb, walkableHeight);

			//Create the voxelizer and set all settings
			var vox = new Voxelize (cellHeight, cellSize, walkableClimb, walkableHeight, maxSlope);
			vox.inputExtraMeshes = extraMeshes;

			vox.maxEdgeLength = maxEdgeLength;

			int lastInfoCallback = -1;
			var watch = System.Diagnostics.Stopwatch.StartNew();

			//Generate all tiles
			for (int z=0;z<td;z++) {
				for (int x=0;x<tw;x++) {

					int tileNum = z*tileXCount + x;
#if !NETFX_CORE || UNITY_EDITOR
					System.Console.WriteLine ("Generating Tile #"+(tileNum) + " of " + td*tw);
#endif

					//Call statusCallback only 10 times since it is very slow in the editor
					if (statusCallback != null && (tileNum*10/tiles.Length > lastInfoCallback || watch.ElapsedMilliseconds > 2000)) {
						lastInfoCallback = tileNum*10/tiles.Length;
						watch.Reset();
						watch.Start();

						statusCallback (new Progress (AstarMath.MapToRange (0.1f, 0.9f, tileNum/(float)tiles.Length), "Building Tile " + tileNum + "/" + tiles.Length));
					}

					BuildTileMesh (vox, x,z);
				}
			}

#if !NETFX_CORE
			System.Console.WriteLine ("Assigning Graph Indices");
#endif

			if (statusCallback != null) statusCallback (new Progress (0.9f, "Connecting tiles"));

			//Assign graph index to nodes
			uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex (this);

			GraphNodeDelegateCancelable del = delegate (GraphNode n) {
				n.GraphIndex = graphIndex;
				return true;
			};
			GetNodes (del);

			for (int z=0;z<td;z++) {
				for (int x=0;x<tw;x++) {
#if !NETFX_CORE
					System.Console.WriteLine ("Connecing Tile #"+(z*tileXCount + x) + " of " + td*tw);
#endif
					if (x < tw-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x+1 + z*tileXCount]);
					if (z < td-1) ConnectTiles (tiles[x + z*tileXCount], tiles[x + (z+1)*tileXCount]);
				}
			}

			AstarProfiler.PrintResults ();
		}