// this function returns back the nearest position on the nav mesh to the passed point // if the point is not on the nav mesh, this function will return a position on the perimeter of the nav mesh. // increase 'NudgeIntoNavMesh' in order to return a point offset into the nav mesh away from the perimeter ('NudgeIntoNavMesh' can be useful for // floating point inacuracies in subsequent nav mesh visibility tests) public static Vector3 CalculatePointOnNavMeshOptimized(Vector3 point, float NudgeIntoNavMesh = 0f, NNInfo?nearestInfo = null) { if (null != AstarPath.active) { NNInfo info = nearestInfo ?? AstarPath.active.GetNearest(point); if (IsPointOnNavMeshOptimized(point, info)) { return(point); } else if (null != info.node) { if (NudgeIntoNavMesh != 0f) { Vector3 diffToTriangleCenter = ((Vector3)info.node.position) - info.clampedPosition; if (diffToTriangleCenter.sqrMagnitude <= NudgeIntoNavMesh * NudgeIntoNavMesh) // check this to avoid exiting the closest node, which may cause an exit of the nav mesh { return(info.clampedPosition + diffToTriangleCenter); // this will put the returned position at the center of the closest node } else { // offset into the closest node by the amount of NudgeIntoNavMesh return(info.clampedPosition + (diffToTriangleCenter.normalized * NudgeIntoNavMesh)); } } else { return(info.clampedPosition); } } } return(point); }
// will return the point at which the line exits the nav mesh, or 'to' if the line does not exit the nav mesh // if 'clampFromInNavMesh' is true, we make sure the from position is on the nav mesh before doing checks // (done in 2d, does not currently support nav meshes on top of one and other) public static Vector3 CalculateExitPointOfRecastGraph(ref Vector3 from, Vector3 to, bool clampFromInNavMesh = false) { NNInfo fromInfo = AstarPath.active.GetNearest(from); if (null == fromInfo.node) { return(from); } if (clampFromInNavMesh) { from = CalculatePointOnRecastGraph(from, 0.1f, fromInfo); } NavGraph graph = AstarData.GetGraph(fromInfo.node); if (graph != null) { IRaycastableGraph rayGraph = graph as IRaycastableGraph; if (rayGraph != null) { GraphHitInfo hit; if (rayGraph.Linecast(from, to, fromInfo.node, out hit)) { return(hit.point); } return(to); // no nav mesh exit } return(from); // no recast graph } return(from); // no nav mesh }
private void SearchPathInArea(Vector3 _dst, Move.PathFinished _arrived) { NNInfo nearest = AstarPath.active.GetNearest(_dst); NNInfo nearest2 = AstarPath.active.GetNearest(this._self.transform.position); if (this.areaNavPath != null) { ListPool <GraphNode <AreaPathfinding.AreaInfo> > .Release(this.areaNavPath); } if (this.areaNavPath == null || this.areaNavPath.Count == 0) { this.areaNavPath = Singleton <AreaPathfinding> .Instance.FindPath((int)nearest2.node.Area, (int)nearest.node.Area); } if (this.areaNavPath != null) { if (this.areaNavPath.Count <= 1) { Debug.LogError("area path find error!"); return; } this.finalDestination = _dst; this.TrySearchPath(this.areaNavPath[0].Value.FindPoint(this.areaNavPath[1].Value.id), _arrived); } else { Debug.LogError(string.Format("Target position cannot be arrived (area{0} to area{1}", (int)nearest2.node.Area, (int)nearest.node.Area)); Singleton <WorldPathfinding> .Instance.StopWorldPathfinding(); this.StopPath(); } }
public override void OnStateEnter(BaseStateMachine m) { Vector2 dir = localFSM.transform.position - ai.target.position; RaycastHit2D hit = Physics2D.Raycast(localFSM.transform.position, dir.normalized, 20, 1 << LayerMask.NameToLayer("Concrete")); if (hit.collider) { NNInfo info = AstarPath.active.GetNearest(hit.point, NNConstraint.Default); escapePoint = info.position; } else { NNInfo info = AstarPath.active.GetNearest((Vector2)localFSM.transform.position + dir.normalized * 20, NNConstraint.Default); escapePoint = info.position; } //Debug.Log("<Color=yellow>MY SPEED IS:</Color>" + ai.controller.speed); ai.OnFinishPath += FinishFleePoint; ai.SetDestination(escapePoint); ai.speed = 3; //throw new System.NotImplementedException(); }
private static bool CalculateNavMeshQueryParams(ref Vector3 from, Vector3 to, ref Vector3 fromNodePos, ref List <ObstacleVertex> obstacles, bool clampFromInNavMesh, Simulator sim) { if (null == AstarPath.active) { return(false); } CreateAllPointsList(); _allPoints.Clear(); _allPoints.Add(from); _allPoints.Add(to); NNInfo fromInfo = AstarPath.active.GetNearest(from); if (null == fromInfo.node) { return(false); } fromNodePos = (Vector3)fromInfo.node.position; _allPoints.Add(fromNodePos); Bounds bounds = GameUtils.CalculateBounds(_allPoints); // calculate the bounding box to encapsulate all points we need to consider // sim.GetObstacles() is an alternative - this may be faster const float SearchPadding = 0.1f; sim.GetStaticAndDynamicObstacles(obstacles, bounds.center, (bounds.max - bounds.center).sqrMagnitude + SearchPadding); // get all obstacles near our line if (clampFromInNavMesh) { from = CalculatePointOnNavMesh(from, sim, 0.1f, fromInfo, obstacles); } return(true); }
public override void OnStateEnter(Animator animator, AnimatorStateInfo animatorStateInfo, int layerIndex) { ai = animator.GetComponent <EnemyAI>(); anim = animator; if (loop) { ai.OnFinishPath += NextPoint; } else { ai.OnFinishPath += Continue; } Vector2 p = Random.insideUnitCircle.normalized; p = p * distance; p = (Vector2)animator.transform.position + p; NNInfo info = AstarPath.active.GetNearest(p); Vector3 closest = info.position; ai.SetDestination(closest); ai.stopMove = false; }
/// <summary> /// Called by all position target setters. Ensures that the position set /// is within the current path finding bounds. <br/>If the point is outside the map, /// we find the nearest point and set as the target, whilst saving the final target position. /// We then pass this final target position /// </summary> /// <param name="target"></param> private void InternalSetTargetPosition(Vector3 target) { if (target == Vector3.zero) { Debug.Log("set target to 0"); } Debug.Log(LoadedEntity.Entity + " again"); //Ensure target is set Target = target; //Find the neasest node NNInfo nninfo = AstarPath.active.GetNearest(target); //If the node is far from the target position, we ensure that the path finder knows //that this is not the final position. if ((target - nninfo.position).XZ().sqrMagnitude > 4) { IsExactTarget = false; TargetObject.transform.position = nninfo.position; //Debug.Log(LoadedEntity.Entity + " has non exact PF: " + nninfo.position + "->" + target); } else { IsExactTarget = true; TargetObject.transform.position = target; //Debug.Log(LoadedEntity.Entity + " has exact PF: " + target); } LoadedEntity.SetLookBasedOnMovement(true); LoadedEntity.SetIdle(false); }
public static UnitState Inertance(this UnitState state, uint inertialFrame) { if (inertialFrame > 10000) { Log.Trace($"模拟帧异常{inertialFrame}"); return(state); } state.Frame += inertialFrame; for (int i = 0; i < inertialFrame; i++) { if (state.Velocity == 0) { continue; } Vector3 move = state.Forward * state.Velocity; NNInfo mapNodeInfo = PathFindHelper.GetNearest(state.Position + move); state.Position = mapNodeInfo.position; if (state.Velocity >= VelocityConst.Deceleration) { state.Velocity -= VelocityConst.Deceleration; } else { state.Velocity = 0; } } return(state); }
// if the ground height cannot be found, this function will set outGroundHeight to the y value of the passed in pos public static bool CalculateGroundHeight(Vector3 pos, int mask, out RaycastHit hit, ref float outGroundHeight) { outGroundHeight = pos.y; const float SphereCastStartYOffset = 5f; // this needs to be large enough that if a character is going up stairs, the start postion of the sphere case will be above the ground // but not too large that the start position may be above a higher level of ground like a bridge overhead const float SphereCastRadius = 0.35f; // this value ensures the sphere cast does not begin intersecting the ground, but is large enough to not go through seems const float GroundClearence = 0.1f; // how much we raise our returned hit point, so things aren't exactly on the ground const float SphereCastLength = 10f; // this needs to be long enough to find ground below 'pos' if (Physics.SphereCast(pos + (Vector3.up * SphereCastStartYOffset), SphereCastRadius, Vector3.down, out hit, SphereCastLength, mask)) { outGroundHeight = hit.point.y + GroundClearence; return(true); } else if (null != AstarPath.active) // the sphere cast should never fail, let's see if starting the sphere cast from the height of the nav mesh makes a difference { NNInfo info = AstarPath.active.GetNearest(pos); if (null != info.node) { pos.y = info.clampedPosition.y; if (Physics.SphereCast(pos + (Vector3.up * SphereCastStartYOffset), SphereCastRadius, Vector3.down, out hit, SphereCastLength, mask)) { outGroundHeight = hit.point.y + GroundClearence; return(true); } } } return(false); }
private bool IsPathPossible(Vector3 dest) { NNInfo nearest = AstarPath.active.GetNearest(dest); NNInfo nearest2 = AstarPath.active.GetNearest(this._self.transform.position); return(nearest2.node.Area == 0u || nearest.node.Area == 0u || nearest2.node.Area == nearest.node.Area); }
/** Find Nearest Hiding Spot * * Recursively search to prevent returning present hiding spot * */ public Vector3 findNearestHide(Vector3 startPos) { Vector3 returnPos; NNInfo info = AstarPath.active.GetNearest(startPos, constraint); returnPos = (Vector3)info.node.position; return(Vector3.Distance(returnPos, startPos) < 2 ? findNearestHide(findRandomEndPoint(startPos)) : returnPos); }
private bool IsTargetReachable(float horizStartSpeed, float horizEndSpeed, float horizAccSpeed) { float num = 0f; if (base.jumpMode == 1) { this.reachMaxTime = base.startVertSpeed / this.gravity * 2f; num = horizStartSpeed * this.reachMaxTime; } else if (base.jumpMode == 2) { float num2 = (horizStartSpeed - horizEndSpeed) / horizAccSpeed; num = horizStartSpeed * num2 - horizAccSpeed * num2 * num2 * 0.5f; this.reachMaxTime += num2; } if (num == 0f) { return(false); } Vector3 position = this._self.transform.position + this._self.transform.forward * num; NNInfo nearest = AstarPath.active.GetNearest(position); if (nearest.node == null || !nearest.node.Walkable) { return(false); } if (base.jumpMode == 1 && nearest.clampedPosition.y > this._self.transform.position.y + 0.1f) { if (nearest.clampedPosition.y > this._self.transform.position.y + this.maxJumpHeight) { return(false); } Vector3 position2 = this._self.transform.position + this._self.transform.forward * num * 0.5f; NNInfo nearest2 = AstarPath.active.GetNearest(position2); float num3 = ((Vector3)nearest2.node.position).y + 0.1f; float num4 = this._self.transform.position.y + this.maxJumpHeight; if (!nearest2.node.Walkable || num3 > num4) { return(false); } } else if (base.jumpMode == 2 && nearest.clampedPosition.y > this._self.transform.position.y + 0.1f) { return(false); } nearest.clampedPosition.y = nearest.clampedPosition.y + 0.5f; RaycastHit[] array = Physics.RaycastAll(nearest.clampedPosition, Vector3.down, 500f); for (int i = 0; i < array.Length; i++) { Transform transform = array[i].transform; NNInfo nearest3 = AstarPath.active.GetNearest(array[i].point); if (transform.gameObject.layer == LayerMask.NameToLayer("Ground") && nearest3.node.Walkable) { return(true); } } return(false); }
// will return false if any part of the line is off the nav mesh // if 'clampFromInNavMesh' is true, we make sure the from position is on the nav mesh before doing checks // (done in 2d, does not currently support nav meshes on top of one and other) public static bool IsVisibleOnNavMeshOptimized(ref Vector3 from, Vector3 to, bool clampFromInNavMesh, NNInfo?nearestInfo, ref Vector3 endPoint, List <TriangleMeshNode> outList) { endPoint = from; if (null == AstarPath.active) { return(false); // no nav mesh } NNInfo fromInfo = nearestInfo ?? AstarPath.active.GetNearest(from); TriangleMeshNode currentTriangle = fromInfo.node as TriangleMeshNode; if (null == currentTriangle) { return(false); // no nav mesh } if (clampFromInNavMesh) { endPoint = from = CalculatePointOnNavMeshOptimized(from, 0.1f, fromInfo); } else if (!currentTriangle.ContainsPoint((Int3)from)) { return(false); // start point is off the nav mesh } bool isVisible = false; AstarPath.active.StartUsingTriangleScratchList(); while (null != currentTriangle) { if (null != outList) { outList.Add(currentTriangle); } TriangleMeshNode nextTriangle = null; if (DoesLineExitTriangle(from, to, currentTriangle, ref AstarPath.active.trianglesHashSet, ref nextTriangle, ref endPoint)) // the end point returned will be on the ground plane (y value zero) { if (null == nextTriangle) // no next triangle, so the line exits off the edge of the nav mesh ('while' loop will end) { VirticalRayPlaneIntersection(new Vector2(endPoint.x, endPoint.z), currentTriangle, ref endPoint); // make sure the endPoint is on the plane of the triangle isVisible = false; // exits the nav mesh } } else // does not exit triangle { VirticalRayPlaneIntersection(new Vector2(to.x, to.z), currentTriangle, ref endPoint); // make sure the endPoint is on the plane of the triangle isVisible = true; // the line cast ends inside this triangle, no nextTriangle, nextTriangle will be null ('while' loop will end) } AstarPath.active.trianglesHashSet.Add(currentTriangle); currentTriangle = nextTriangle; } AstarPath.active.StopUsingTriangleScratchList(); return(isVisible); }
private void Update() { if (this.status == PunchAway.Status.None) { return; } if (this.status != PunchAway.Status.Ground) { this.curUpSpeed -= this.gravity * Time.fixedDeltaTime; } else { this.curHorizStartSpeed -= this.curHorizDeceleration * Time.fixedDeltaTime; } if (this.curUpSpeed <= 0f && this.status == PunchAway.Status.Up) { this.status = PunchAway.Status.Down; } float num = this.curUpSpeed * Time.fixedDeltaTime; Vector3 vector2; if (this.curHorizStartSpeed >= 0f) { Vector3 a = (!(this.self.attacker != null)) ? (-this.self.transform.forward) : (this.self.transform.position - this.self.attacker.transform.position).normalized; Vector3 vector = a * this.curHorizStartSpeed * Time.fixedDeltaTime; vector2 = new Vector3(vector.x + this.self.transform.position.x, num + this.self.transform.position.y, vector.z + this.self.transform.position.z); } else { vector2 = new Vector3(this.self.transform.position.x, num + this.self.transform.position.y, this.self.transform.position.z); } bool flag = false; RaycastHit[] array = Physics.RaycastAll(vector2, Vector3.down, 200f); for (int i = 0; i < array.Length; i++) { NNInfo nearest = AstarPath.active.GetNearest(array[i].point); if (array[i].transform.gameObject.layer == LayerMask.NameToLayer("Ground") && nearest.node.Walkable) { flag = true; break; } } if (!flag) { this.ClearSpeed(); } else { this.self.transform.position = vector2; } }
public override bool SamplePosition(Vector3 center, out Vector3 hitLocation, float radius = 0.5f) { NNInfo info = AstarPath.active.GetNearest(center, NNConstraint.Default); if (info.node.Walkable) { hitLocation = info.position; return(true); } hitLocation = Vector3.positiveInfinity; return(false); }
// checks to see if the point is actually inside the closest triangle on the nav mesh public static bool IsPointOnNavMeshOptimized(Vector3 point, NNInfo?nearestInfo = null) { if (null != AstarPath.active) { NNInfo pointInfo = nearestInfo ?? AstarPath.active.GetNearest(point); TriangleMeshNode closestTriangle = pointInfo.node as TriangleMeshNode; if (null != closestTriangle) { return(closestTriangle.ContainsPoint((Int3)point)); } } return(false); }
public NNInfo GetNextNode(float minDistance) { Vector3 waypointPos = this.Leader.GetNextWayPoint(minDistance); if (waypointPos == Vector3.zero) { NNInfo nni = new NNInfo(); return(nni); } NNInfo node = AstarPath.active.astarData.pointGraph.GetNearest(waypointPos); return(node); }
public Vector3 ClampToNavmesh(Vector3 target) { if (prevNode == null) { NNInfo nninfo = AstarPath.active.GetNearest(transform.position); prevNode = nninfo.node; prevPos = transform.position; } Vector3 newPos; prevNode = ClampAlongNavmesh(prevPos, prevNode, target, out newPos); prevPos = newPos; return(newPos); }
public void AdjustRelativePositions(Vector3 anchorPoint, Vector3 orientation) { Quaternion orientationRotationQuat = Quaternion.LookRotation(orientation, Vector3.up); for (int i = 0; i < formationSpots.Length; i++) { Vector3 theoreticalRealPos = anchorPoint + orientationRotationQuat * formationSpots[i].offset * spacingScale; NNInfo info = AstarPath.active.GetNearest(theoreticalRealPos); Vector3 closest = info.position; //formationSpots[i].adjustedPosition = closest; formationSpots[i].marksPath.Add(closest); } }
public void NextPoint() { Vector2 p = Random.insideUnitCircle.normalized; p = p * distance; p = (Vector2)ai.transform.position + p; NNInfo info = AstarPath.active.GetNearest(p); Vector3 closest = info.position; ai.SetDestination(closest); }
private Vector3 GetWalkablePointWhenFalldown(Vector3 position, Vector3 dir, float decrement) { if (decrement > 0f) { Debug.LogError("增量只能为负数"); return(Vector3.zero); } Vector3 position2 = position + dir * decrement; NNInfo nearest = AstarPath.active.GetNearest(position2); if (nearest.node.Walkable) { return(nearest.clampedPosition); } return(this.GetWalkablePointWhenFalldown(position, dir, decrement - 0.5f)); }
// checks to see if their is an obstacle between the point and the center of the closest node on the nav mesh public static bool IsPointOnRecastGraph(Vector3 point, NNInfo?nearestInfo = null) { NNInfo info = nearestInfo ?? AstarPath.active.GetNearest(point); NavGraph graph = AstarData.GetGraph(info.node); if (graph != null) { IRaycastableGraph rayGraph = graph as IRaycastableGraph; if (rayGraph != null) { GraphHitInfo hit; return(!rayGraph.Linecast(((Vector3)info.node.position), point, info.node, out hit)); } return(false); // no recast graph } return(false); // no nav mesh }
// Update is called once per frame void LateUpdate() { if (prevNode == null) { NNInfo nninfo = AstarPath.active.GetNearest(transform.position); prevNode = nninfo.node; prevPos = transform.position; } if (prevNode == null) { return; } if (prevNode != null) { IRaycastableGraph graph = AstarData.GetGraph(prevNode) as IRaycastableGraph; if (graph != null) { GraphHitInfo hit; if (graph.Linecast(prevPos, transform.position, prevNode, out hit)) { hit.point.y = transform.position.y; Vector3 closest = Mathfx.NearestPoint(hit.tangentOrigin, hit.tangentOrigin + hit.tangent, transform.position); if (graph.Linecast(hit.point, closest, hit.node, out hit)) { hit.point.y = transform.position.y; transform.position = hit.point; } else { closest.y = transform.position.y; transform.position = closest; } } prevNode = hit.node; } } prevPos = transform.position; }
private void CallPacementOfNodes(bool isMouseDown) { Camera cam = SceneView.lastActiveSceneView.camera; Vector3 mousepos = Event.current.mousePosition; mousepos.z = -cam.worldToCameraMatrix.MultiplyPoint(thisObject.transform.position).z; mousepos.y = Screen.height - mousepos.y - 36.0f; // ??? Why that offset?! mousepos = cam.ScreenToWorldPoint(mousepos); thisObject.mousePositionWorld = mousepos; RaycastHit hit; if (Physics.Raycast(cam.transform.position, thisObject.mousePositionWorld - cam.transform.position, out hit, 200)) { if (hit.transform != null) { // Check if the first grid graph in the scene has any nodes // if it doesn't then it is not scanned. if (AstarPath.active.data.gridGraph.nodes == null) { AstarPath.active.Scan(); } NNInfo info = AstarPath.active.GetNearest(hit.point); GraphNode node = info.node; if (!graphData.Contains(node)) { CreateNode(node); graphData.Add(node); } else if (isMouseDown) { RemoveNode(node, isMouseDown); return; } } } }
protected void FixedUpdate() { ActiveDungeon activeDungeon = Binder.GameState.ActiveDungeon; if ((activeDungeon != null) && (activeDungeon.ActiveRoom != null)) { this.freeOccupiedNodes(); for (int i = 0; i < activeDungeon.ActiveRoom.ActiveCharacters.Count; i++) { CharacterInstance instance = activeDungeon.ActiveRoom.ActiveCharacters[i]; if (!instance.IsDead) { uint tag = 0; if (instance.IsSupport) { tag = 0x1f; } else if (instance.IsPlayerCharacter) { tag = 30; } else { tag = 0x1d; } NNInfo nearest = activeDungeon.ActiveRoom.AstarPath.GetNearest(instance.PhysicsBody.Transform.position, this.m_defaultAstarConstraint); if (nearest.node != null) { this.occupyNode(nearest.node, tag); if (!instance.IsPlayerCharacter) { List <GraphNode> list = this.getNodeConnections(nearest); for (int j = 0; j < list.Count; j++) { this.occupyNode(list[j], tag); } } } } } } }
public override void OnStateEnter(Animator animator, AnimatorStateInfo animatorStateInfo, int layerIndex) { ai = animator.GetComponent <MyAI>(); ai.OnFinishPath = NextPoint; Vector2 p = Random.insideUnitCircle.normalized; p = p * 2; p = (Vector2)animator.transform.position + p; NNInfo info = AstarPath.active.GetNearest(p); Vector3 closest = info.position; ai.SetDestination(closest); }
// checks to see if their is an obstacle between the point and the center of the closest node on the nav mesh public static bool IsPointOnNavMesh(Vector3 point, Simulator sim, NNInfo?nearestInfo = null, List <ObstacleVertex> obstaclesToTest = null) { if (null != AstarPath.active) { NNInfo info = nearestInfo ?? AstarPath.active.GetNearest(point); if (null != info.node) { Vector3 nodePos = (Vector3)info.node.position; if (null == obstaclesToTest) { AstarPath.active.StartUsingObstaclesScratchList(); // sim.GetObstacles() is an alternative - this may be faster Vector3 center = Vector3.Lerp(nodePos, point, 0.5f); const float SearchPadding = 0.1f; sim.GetStaticAndDynamicObstacles(AstarPath.active.obstaclesScratchList, center, (nodePos - center).sqrMagnitude + SearchPadding); for (int i = 0; i < AstarPath.active.obstaclesScratchList.Count; i++) { // do a 2d line intersection check to see if the line goes off the nav mesh if (VectorMath.SegmentsIntersectXZ(nodePos, point, AstarPath.active.obstaclesScratchList[i].position, AstarPath.active.obstaclesScratchList[i].next.position)) { AstarPath.active.StopUsingObstaclesScratchList(); return(false); // the point is off the nav mesh } } AstarPath.active.StopUsingObstaclesScratchList(); } else // null != obstaclesToTest { for (int i = 0; i < obstaclesToTest.Count; i++) { // do a 2d line intersection check to see if the line goes off the nav mesh if (VectorMath.SegmentsIntersectXZ(nodePos, point, obstaclesToTest[i].position, obstaclesToTest[i].next.position)) { return(false); // the point is off the nav mesh } } } return(true); // the point is on the nav mesh } } return(false); }
private async void MoveUpdate() { while (Application.isPlaying) { Vector2 axis = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); if (axis != Vector2.zero) { Vector3 move = new Vector3(axis.x, 0, axis.y).normalized * 0.05f * this.Speed; NNInfo nearInfo = PathFindHelper.GetNearest(this.virtualPos + move); if (nearInfo.position != this.virtualPos) { this.virtualPos = nearInfo.position; this.movePath.Enqueue(this.virtualPos); } } await Task.Delay(50); } }
// will return false if any part of the line is off the nav mesh // if 'clampFromInNavMesh' is true, we make sure the from position is on the nav mesh before doing checks // (done in 2d, does not currently support nav meshes on top of one and other) public static bool IsVisibleOnRecastGraph(Vector3 from, Vector3 to, bool clampFromInNavMesh = false, NNInfo?nearestInfo = null) { if (null == AstarPath.active) { return(false); } NNInfo fromInfo = nearestInfo ?? AstarPath.active.GetNearest(from); if (null == fromInfo.node) { return(false); } if (clampFromInNavMesh) { from = CalculatePointOnRecastGraph(from, 0.1f, fromInfo); } NavGraph graph = AstarData.GetGraph(fromInfo.node); if (graph != null) { IRaycastableGraph rayGraph = graph as IRaycastableGraph; if (rayGraph != null) { GraphHitInfo hit; if (rayGraph.Linecast(from, to, fromInfo.node, out hit)) { return(false); // hit an obstacle } return(true); // no nav mesh exit } return(false); // no recast graph } return(false); // no nav mesh }
// recalculate the link start and end nodes private void Recalculate() { BoxCollider collider = GetComponent <BoxCollider>(); NNInfo startInfo = AstarPath.active.GetNearest(CalculateStartLocation(collider)); NNInfo destInfo = AstarPath.active.GetNearest(CalculateDestLocation(collider)); // if either is null, or they're the same, then nothing is being linked to anything else if (startInfo.node == null || destInfo.node == null || startInfo.node.Area == destInfo.node.Area) { #if UNITY_EDITOR && DEBUG _startNodePosition = _destNodePosition = null; #endif return; } #if UNITY_EDITOR && DEBUG _startNodePosition = startInfo.node; _destNodePosition = destInfo.node; #endif // add the start links HashSet <uint> startLinks = (HashSet <uint>)_bridgeLinks[startInfo.node.Area]; if (null == startLinks) { startLinks = new HashSet <uint>(); _bridgeLinks[startInfo.node.Area] = startLinks; } startLinks.Add(destInfo.node.Area); // add the destination links HashSet <uint> destLinks = (HashSet <uint>)_bridgeLinks[destInfo.node.Area]; if (null == destLinks) { destLinks = new HashSet <uint>(); _bridgeLinks[destInfo.node.Area] = destLinks; } destLinks.Add(startInfo.node.Area); }