public GetInRange ( |
||
point | Nodes around this point will be added to the buffer. | |
sqrRadius | long | squared maximum distance in Int3 space. If you are converting from world space you will need to multiply by Int3.Precision:
/// var sqrRadius = (worldSpaceRadius * Int3.Precision) * (worldSpaceRadius * Int3.Precision); |
buffer | List | All nodes will be added to this list. |
return | void |
/// <summary> /// Calculates connections for all nodes in the graph. /// This is an IEnumerable, you can iterate through it using e.g foreach to get progress information. /// </summary> IEnumerable <Progress> ConnectNodesAsync() { if (maxDistance >= 0) { // To avoid too many allocations, these lists are reused for each node var connections = new List <Connection>(); var candidateConnections = new List <GraphNode>(); long maxSquaredRange; // Max possible squared length of a connection between two nodes // This is used to speed up the calculations by skipping a lot of nodes that do not need to be checked if (maxDistance == 0 && (limits.x == 0 || limits.y == 0 || limits.z == 0)) { maxSquaredRange = long.MaxValue; } else { maxSquaredRange = (long)(Mathf.Max(limits.x, Mathf.Max(limits.y, Mathf.Max(limits.z, maxDistance))) * Int3.Precision) + 1; maxSquaredRange *= maxSquaredRange; } // Report progress every N nodes const int YieldEveryNNodes = 512; // Loop through all nodes and add connections to other nodes for (int i = 0; i < nodeCount; i++) { if (i % YieldEveryNNodes == 0) { yield return(new Progress(i / (float)nodeCount, "Connecting nodes")); } connections.Clear(); var node = nodes[i]; if (optimizeForSparseGraph) { candidateConnections.Clear(); lookupTree.GetInRange(node.position, maxSquaredRange, candidateConnections); for (int j = 0; j < candidateConnections.Count; j++) { var other = candidateConnections[j] as PointNode; float dist; if (other != node && IsValidConnection(node, other, out dist)) { connections.Add(new Connection( other, /// <summary>TODO: Is this equal to .costMagnitude</summary> (uint)Mathf.RoundToInt(dist * Int3.FloatPrecision) )); } } } else { // Only brute force is available in the free version for (int j = 0; j < nodeCount; j++) { if (i == j) { continue; } PointNode other = nodes[j]; float dist; if (IsValidConnection(node, other, out dist)) { connections.Add(new Connection( other, /// <summary>TODO: Is this equal to .costMagnitude</summary> (uint)Mathf.RoundToInt(dist * Int3.FloatPrecision) )); } } } node.connections = connections.ToArray(); node.SetConnectivityDirty(); } } }
public override IEnumerable <Progress> ScanInternal() { yield return(new Progress(0, "Searching for GameObjects")); 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; yield break; } yield return(new Progress(0.1f, "Creating nodes")); //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); } int startID = 0; AddChildren(ref startID, root); } } if (optimizeForSparseGraph) { yield return(new Progress(0.15f, "Building node lookup")); RebuildNodeLookup(); } if (maxDistance >= 0) { // To avoid too many allocations, these lists are reused for each node var connections = new List <PointNode>(); var costs = new List <uint>(); var candidateConnections = new List <GraphNode>(); // Max possible squared length of a connection between two nodes // This is used to speed up the calculations by skipping a lot of nodes that do not need to be checked long maxPossibleSqrRange; if (maxDistance == 0 && (limits.x == 0 || limits.y == 0 || limits.z == 0)) { maxPossibleSqrRange = long.MaxValue; } else { maxPossibleSqrRange = (long)(Mathf.Max(limits.x, Mathf.Max(limits.y, Mathf.Max(limits.z, maxDistance))) * Int3.Precision) + 1; maxPossibleSqrRange *= maxPossibleSqrRange; } // Report progress every N nodes const int YieldEveryNNodes = 512; // Loop through all nodes and add connections to other nodes for (int i = 0; i < nodes.Length; i++) { if (i % YieldEveryNNodes == 0) { yield return(new Progress(Mathf.Lerp(0.15f, 1, i / (float)nodes.Length), "Connecting nodes")); } connections.Clear(); costs.Clear(); PointNode node = nodes[i]; if (optimizeForSparseGraph) { candidateConnections.Clear(); lookupTree.GetInRange(node.position, maxPossibleSqrRange, candidateConnections); System.Console.WriteLine(i + " " + candidateConnections.Count); for (int j = 0; j < candidateConnections.Count; j++) { var other = candidateConnections[j] as PointNode; float dist; if (other != node && IsValidConnection(node, other, out dist)) { connections.Add(other); /** \todo Is this equal to .costMagnitude */ costs.Add((uint)Mathf.RoundToInt(dist * Int3.FloatPrecision)); } } } 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; 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(); } } }