//-------------------------------------------------- // Forward motion means moving from node A to node B, // B to A for backwards motion. Next segment is found // by matching the end node to the beginning node of // another segment //-------------------------------------------------- public WPSegment GetNextSeg(WPSegment curSeg, bool reverse) { WPNode curNode = (!reverse) ? curSeg.nodeB : curSeg.nodeA; // Cache the end node of the first segment WPSegment nextSeg = null; foreach (var s in segments) { if (!reverse) { if (s.nodeA == curNode) { nextSeg = s; break; } } else { if (s.nodeB == curNode) { nextSeg = s; break; } } } if (nextSeg == null) { Debug.Log("Next segment not found. Path is complete or destroyed."); } return(nextSeg); }
//-------------------------------------------------- // Get a new segment from the pool. //-------------------------------------------------- public WPSegment GetSeg(WPNode nodeA, WPNode nodeB, Vector3[] subNodes) { WPSegment returnVal = null; for (int i = 0; i < pool.Count; ++i) { // If a segment with the same start and end node is found in the pool, // return that. No need to make a new object. if (pool[i].nodeA == nodeA && pool[i].nodeB == nodeB) { returnVal = pool[i]; break; } // Otherwise, check to see if there is another pool object that's ready // to be recycled (dead) in the pool. If so, use that. if (pool[i].isDead) { returnVal = pool[i]; } } if (returnVal == null) // Only if there are no matching or dead segments, create a new object. { returnVal = new WPSegment(nodeA, nodeB, subNodes); //Debug.Log("new segment created"); pool.Add(returnVal); } else // Otherwise populate the recycled object with the desired values. { returnVal.nodeA = nodeA; returnVal.nodeB = nodeB; returnVal.subNodes = subNodes; } return(returnVal); }
//-------------------------------------------------- // Main traversal loop //-------------------------------------------------- void TraverseLoop() { if (curSeg == null) { return; } int lastSubNode = curSeg.subNodes.Length - 1; Vector3 curPos = (useRigidbody) ? rb.position : transform.position; bool willOvershoot = false; // Prevent unforseen endless loop float failsafe = 0.0f; const float failsafeTime = 0.5f; // if movement method returns that speed will overshoot, // keep running through segments until it no longer will. do { Vector3 dest = controller.transform.position + curSeg.subNodes[curSub]; willOvershoot = MoveBySpeed(dest, moveSpeed, ref curPos); if (willOvershoot) { curSub += (reverse) ? -1 : 1; } if (curSub < 0 || curSub > lastSubNode) { WPNode curNode = (!reverse) ? curSeg.nodeB : curSeg.nodeA; if (curNode.changeDirection) { reverse = !reverse; // if changing direction, no need to find new seg, just reset subnode } else { curSeg = controller.GetNextSeg(curSeg, reverse); } if (curSeg == null) { Debug.Log("Traversal complete: " + gameObject.name); traversing = false; return; } curSub = (reverse) ? lastSubNode - 1 : 1; } failsafe += Time.deltaTime; } while (willOvershoot && failsafe < failsafeTime); if (!willOvershoot) { if (useRigidbody) { rb.MovePosition(curPos); } else { transform.position = curPos; } } }
public WPSegment(WPNode nodeA, WPNode nodeB, Vector3[] subNodes) { this.nodeA = nodeA; this.nodeB = nodeB; this.subNodes = subNodes; }