예제 #1
0
        /** Check if a straight path between v1 and v2 is valid.
         * If both \a n1 and \a n2 are supplied it is assumed that the line goes from the center of \a n1 to the center of \a n2 and a more optimized graph linecast may be done.
         */
        protected bool ValidateLine(GraphNode n1, GraphNode n2, Vector3 v1, Vector3 v2)
        {
            if (useRaycasting)
            {
                // Use raycasting to check if a straight path between v1 and v2 is valid
                if (use2DPhysics)
                {
                    if (thickRaycast && thickRaycastRadius > 0 && Physics2D.CircleCast(v1 + raycastOffset, thickRaycastRadius, v2 - v1, (v2 - v1).magnitude, mask))
                    {
                        return(false);
                    }

                    if (Physics2D.Linecast(v1 + raycastOffset, v2 + raycastOffset, mask))
                    {
                        return(false);
                    }
                }
                else
                {
                    // Perform a thick raycast (if enabled)
                    if (thickRaycast && thickRaycastRadius > 0 && Physics.SphereCast(new Ray(v1 + raycastOffset, v2 - v1), thickRaycastRadius, (v2 - v1).magnitude, mask))
                    {
                        return(false);
                    }

                    // Perform a normal raycast
                    // This is done even if a thick raycast is also done because thick raycasts do not report collisions for
                    // colliders that overlapped the (imaginary) sphere at the origin of the thick raycast.
                    // If this raycast was not done then some obstacles could be missed.
                    if (Physics.Linecast(v1 + raycastOffset, v2 + raycastOffset, mask))
                    {
                        return(false);
                    }
                }
            }

            if (useGraphRaycasting)
            {
#if !AstarFree && !ASTAR_NO_GRID_GRAPH
                bool betweenNodeCenters = n1 != null && n2 != null;
#endif
                if (n1 == null)
                {
                    n1 = PathFindHelper.GetNearest(v1).node;
                }
                if (n2 == null)
                {
                    n2 = PathFindHelper.GetNearest(v2).node;
                }

                if (n1 != null && n2 != null)
                {
                    // Use graph raycasting to check if a straight path between v1 and v2 is valid
                    NavGraph graph  = UnityHelper.GetGraph(n1);
                    NavGraph graph2 = UnityHelper.GetGraph(n2);

                    if (graph != graph2)
                    {
                        return(false);
                    }

                    var rayGraph = graph as IRaycastableGraph;

                    if (rayGraph != null)
                    {
                        return(!rayGraph.Linecast(v1, v2, n1));
                    }
                }
            }
            return(true);
        }
예제 #2
0
        /** Called when a requested path has been calculated.
         * A path is first requested by #UpdatePath, it is then calculated, probably in the same or the next frame.
         * Finally it is returned to the seeker which forwards it to this function.
         */
        protected override void OnPathComplete(Path newPath)
        {
            ABPath p = newPath as ABPath;

            if (p == null)
            {
                throw new System.Exception("This function only handles ABPaths, do not use special path types");
            }

            waitingForPathCalculation = false;

            // Increase the reference count on the new path.
            // This is used for object pooling to reduce allocations.
            p.Claim(this);

            // Path couldn't be calculated of some reason.
            // More info in p.errorLog (debug string)
            if (p.error)
            {
                p.Release(this);
                return;
            }

            // Release the previous path.
            if (path != null)
            {
                path.Release(this);
            }

            // Replace the old path
            path = p;

            // Make sure the path contains at least 2 points
            if (path.vectorPath.Count == 1)
            {
                path.vectorPath.Add(path.vectorPath[0]);
            }
            interpolator.SetPath(path.vectorPath);

            var graph = UnityHelper.GetGraph(path.path[0]) as ITransformedGraph;

            movementPlane = graph != null ? graph.transform : (rotationIn2D ? new GraphTransform(Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(-90, 270, 90), Vector3.one)) : GraphTransform.identityTransform);

            // Reset some variables
            reachedEndOfPath = false;

            // Simulate movement from the point where the path was requested
            // to where we are right now. This reduces the risk that the agent
            // gets confused because the first point in the path is far away
            // from the current position (possibly behind it which could cause
            // the agent to turn around, and that looks pretty bad).
            interpolator.MoveToLocallyClosestPoint((GetFeetPosition() + p.originalStartPoint.ToUnityV3()) * 0.5f);
            interpolator.MoveToLocallyClosestPoint(GetFeetPosition());

            // Update which point we are moving towards.
            // Note that we need to do this here because otherwise the remainingDistance field might be incorrect for 1 frame.
            // (due to interpolator.remainingDistance being incorrect).
            interpolator.MoveToCircleIntersection2D(position, pickNextWaypointDist, movementPlane);

            var distanceToEnd = remainingDistance;

            if (distanceToEnd <= endReachedDistance)
            {
                reachedEndOfPath = true;
                OnTargetReached();
            }
        }