/// <summary>
        /// Processes the result.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <param name="steerer">The steerer.</param>
        /// <returns>
        ///   <c>true</c> if the result was handled by this processor, otherwise <c>false</c>
        /// </returns>
        public override bool HandleResult(PathResult result, SteerForPathComponent steerer)
        {
            switch (result.status)
            {
                case PathingStatus.DestinationBlocked:
                {
                    var request = result.originalRequest;

                    //Try to find an unobstructed cell as close to the original destination as possible
                    var toGrid = GridManager.instance.GetGrid(request.to);
                    if (toGrid == null)
                    {
                        return false;
                    }

                    var newDestination = toGrid.GetNearestWalkableCell(
                                            request.to,
                                            this.transform.position,
                                            false,
                                            this.maxCellDistanceForNewDestination,
                                            request.requesterProperties);

                    if (newDestination != null)
                    {
                        request.to = newDestination.position;
                        steerer.RequestPath(request);
                        return true;
                    }

                    break;
                }
            }

            return false;
        }
        /// <summary>
        /// Processes the result.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <param name="steerer">The steerer.</param>
        /// <returns>
        ///   <c>true</c> if the result was handled by this processor, otherwise <c>false</c>
        /// </returns>
        public override bool HandleResult(PathResult result, SteerForPathComponent steerer)
        {
            switch (result.status)
            {
                case PathingStatus.NoRouteExists:
                {
                    var request = result.originalRequest;

                    if (_retries < this.maxRetries)
                    {
                        _retries++;

                        request.type = RequestType.Normal;

                        //Having this as a separate call apparently avoids allocation of anonymous method, which otherwise happens even if the status is not the one triggering this action.
                        IssueRequest(request, steerer);
                        return true;
                    }

                    break;
                }
            }

            _retries = 0;
            return false;
        }
Example #3
0
        public IEnumerator ProcessRequestCoroutineInternal(IPathRequest request)
        {
            //Granted this could be done smarter, but since this is not an expected scenario, we just use exception handling to handle it.
            ValidateRequest(request);

            _currentResult = new PathResult(PathingStatus.Complete, null, 0, request);

            var status = PathingStatus.Complete;

            //Iterate over the waypoints of the request, including the end point
            _segmentRequest.Start(request);

            do
            {
                status = StartPathSegment();
                if (status != PathingStatus.Running)
                {
                    break;
                }

                while (status == PathingStatus.Running)
                {
                    status = ProcessNext();
                    yield return(null);
                }

                if (!CompletePathSegment(status))
                {
                    break;
                }
            }while (_segmentRequest.MoveNext());

            if (status != PathingStatus.Complete)
            {
                if (_segments.count > 0)
                {
                    _currentResult.RegisterPartialResult(status, _segmentRequest.GetPendingWaypoints());
                }
                else
                {
                    _currentResult.status = status;
                }
            }

            //Splice the path segments and complete the request
            _currentResult.path = Path.FromSegments(_segments);
            request.Complete(_currentResult);

            _segments.Clear();
            _segmentRequest.Clear();
            _currentResult = null;
        }
Example #4
0
        private void FailRequest(IPathRequest request, Exception e)
        {
            _segments.Clear();
            _segmentRequest.Clear();
            _currentResult = null;

            var result = new PathResult(PathingStatus.Failed, null, 0, request)
            {
                errorInfo = string.Concat(e.Message, Environment.NewLine, e.StackTrace)
            };

            request.Complete(result);
        }
 /// <summary>
 /// Processes the result.
 /// </summary>
 /// <param name="result">The result.</param>
 /// <param name="steerer">The steerer.</param>
 /// <returns>
 ///   <c>true</c> if the result was handled by this processor, otherwise <c>false</c>
 /// </returns>
 public abstract bool HandleResult(PathResult result, SteerForPathComponent steerer);
Example #6
0
 public void Complete(PathResult result)
 {
     throw new InvalidOperationException();
 }
Example #7
0
 /// <summary>
 /// Completes this request
 /// </summary>
 /// <param name="result">The result.</param>
 void IPathRequest.Complete(PathResult result)
 {
     this.requester.ConsumePathResult(result);
 }
Example #8
0
        public IEnumerator ProcessRequestCoroutineInternal(IPathRequest request)
        {
            //Granted this could be done smarter, but since this is not an expected scenario, we just use exception handling to handle it.
            ValidateRequest(request);

            _currentResult = new PathResult(PathingStatus.Complete, null, 0, request);

            var status = PathingStatus.Complete;

            //Iterate over the waypoints of the request, including the end point
            _segmentRequest.Start(request);

            do
            {
                status = StartPathSegment();
                if (status != PathingStatus.Running)
                {
                    break;
                }

                while (status == PathingStatus.Running)
                {
                    status = ProcessNext();
                    yield return null;
                }

                if (!CompletePathSegment(status))
                {
                    break;
                }
            }
            while (_segmentRequest.MoveNext());

            if (status != PathingStatus.Complete)
            {
                if (_segments.count > 0)
                {
                    _currentResult.RegisterPartialResult(status, _segmentRequest.GetPendingWaypoints());
                }
                else
                {
                    _currentResult.status = status;
                }
            }

            //Splice the path segments and complete the request
            _currentResult.path = Path.FromSegments(_segments);
            request.Complete(_currentResult);

            _segments.Clear();
            _segmentRequest.Clear();
            _currentResult = null;
        }
Example #9
0
        private void FailRequest(IPathRequest request, Exception e)
        {
            _segments.Clear();
            _segmentRequest.Clear();
            _currentResult = null;

            var result = new PathResult(PathingStatus.Failed, null, 0, request)
            {
                errorInfo = string.Concat(e.Message, Environment.NewLine, e.StackTrace)
            };

            request.Complete(result);
        }
        //Note this may be called from another thread if the PathService is running asynchronously
        void INeedPath.ConsumePathResult(PathResult result)
        {
            lock (_syncLock)
            {
                //If we have stooped or get back the result of a request other than the one we currently expect, just toss it as it will be outdated.
                if (_stopped || result.originalRequest != _pendingPathRequest)
                {
                    return;
                }

                _pendingResult = result;
                _pendingPathRequest = null;
            }
        }
 void INeedPath.ConsumePathResult(PathResult result)
 {
     LoadBalancer.marshaller.ExecuteOnMainThread(() => _callback(result));
 }
        /// <summary>
        /// The path request callback method.
        /// </summary>
        /// <param name="result">The path result.</param>
        /// <param name="unit">This unit's UnitFacade.</param>
        /// <param name="unitPos">This unit's position.</param>
        /// <param name="destination">The destination.</param>
        /// <param name="grid">The grid.</param>
        private void PathRequestCallback(PathResult result, IUnitFacade unit, Vector3 unitPos, Vector3 destination, IGrid grid)
        {
            // if the normal path request fails...
            Action<PathResult> callback = (secondResult) =>
            {
                if (secondResult.status == PathingStatus.Complete)
                {
                    // add the unit's current position to the path
                    var path = result.path;
                    path.Push(unit);

                    FollowPath(path, unit);
                    return;
                }

                // if the second path request fails, there is nothing to do
                _stopped = true;
            };

            // try to request a path from the nearest (from) walkable cell
            Cell fromCell = grid.GetNearestWalkableCell(unitPos, unitPos, true, 1, unit);
            if (fromCell != null)
            {
                QueuePathRequest(fromCell.position, destination, unit, callback);
                return;
            }

            // if that fails, search through all 8 neighbour cells and attempt to request a path from the nearest isWalkable neighbour
            int neighboursCount = _neighbours.count;
            for (int i = 0; i < neighboursCount; i++)
            {
                var neighbourCell = _neighbours[i];
                if (neighbourCell.isWalkable(unit.attributes))
                {
                    QueuePathRequest(neighbourCell.position, destination, unit, callback);
                    return;
                }
            }
        }
        private bool ProcessAndValidateResult(PathResult result, bool isWaypoint)
        {
            _wayPoints.frozen = false;

            for (int i = 0; i < _resultProcessors.Length; i++)
            {
                if (_resultProcessors[i].HandleResult(result, this))
                {
                    return (result.status == PathingStatus.Complete);
                }
            }

            var status = result.status;
            bool isPartial = (status == PathingStatus.CompletePartial);
            if (isPartial)
            {
                status = result.innerResult.status;
            }

            switch (status)
            {
                case PathingStatus.Complete:
                {
                    /* All is good, no more to do */
                    _arrivalEvent = UnitNavigationEventMessage.Event.DestinationReached;
                    return true;
                }

                case PathingStatus.NoRouteExists:
                case PathingStatus.EndOutsideGrid:
                {
                    _arrivalEvent = UnitNavigationEventMessage.Event.StoppedNoRouteExists;
                    break;
                }

                case PathingStatus.StartOutsideGrid:
                {
                    _arrivalEvent = UnitNavigationEventMessage.Event.StoppedUnitOutsideGrid;
                    break;
                }

                case PathingStatus.DestinationBlocked:
                {
                    _arrivalEvent = UnitNavigationEventMessage.Event.StoppedDestinationBlocked;
                    break;
                }

                case PathingStatus.Decayed:
                {
                    //We cannot reissue the request here, since we may be on a different thread, but then again why would we issue the request again if it had a decay threshold its no longer valid.
                    _arrivalEvent = UnitNavigationEventMessage.Event.StoppedRequestDecayed;
                    break;
                }

                case PathingStatus.Failed:
                {
                    StopInternal();
                    Debug.LogError("Path request failed: " + result.errorInfo);
                    break;
                }
            }

            _wayPoints.frozen = true;

            if (isPartial)
            {
                return true;
            }

            if (!isWaypoint)
            {
                //If we are not already moving stop and announce here
                StopAndAnnounceArrival();
            }

            return false;
        }
        private bool ProcessAndValidateResult(PathResult result)
        {
            UnitNavigationEventMessage.Event msgEvent = UnitNavigationEventMessage.Event.None;

            switch (result.status)
            {
                case PathingStatus.Complete:
                {
                    /* All is good, no more to do */
                    return true;
                }

                case PathingStatus.NoRouteExists:
                case PathingStatus.EndOutsideGrid:
                {
                    msgEvent = UnitNavigationEventMessage.Event.StoppedNoRouteExists;
                    break;
                }

                case PathingStatus.StartOutsideGrid:
                {
                    msgEvent = UnitNavigationEventMessage.Event.StoppedUnitOutsideGrid;
                    break;
                }

                case PathingStatus.DestinationBlocked:
                {
                    msgEvent = UnitNavigationEventMessage.Event.StoppedDestinationBlocked;
                    break;
                }

                case PathingStatus.Decayed:
                {
                    //We cannot reissue the request here, since we may be on a different thread, but then again why would we issue the request again if it had a decay threshold its no longer valid.
                    msgEvent = UnitNavigationEventMessage.Event.StoppedRequestDecayed;
                    break;
                }

                case PathingStatus.Failed:
                {
                    Debug.LogError("Path request failed: " + result.errorInfo);
                    break;
                }
            }

            var destination = result.originalRequest.to;
            var pendingWaypoints = _wayPoints.count > 0 ? _wayPoints.ToArray() : Consts.EmptyVectorArray;

            Stop();

            if (msgEvent != UnitNavigationEventMessage.Event.None)
            {
                AnnounceEvent(msgEvent, destination, pendingWaypoints);
            }

            return false;
        }
Example #15
0
        private void CompleteRequest(PathingStatus status)
        {
            PathResult result;

            if (_currentRequest.type == RequestType.IntelOnly)
            {
                result = new PathResult(status, null, _goal.g, _currentRequest);
            }
            else if (status == PathingStatus.Complete)
            {
                Path path;

                var maxPathLength = Mathf.CeilToInt(_goal.g / (_goal.parent.cellSize * _costProvider.baseMoveCost));

                //Fix the actual destination so it does not overlap obstructions
                FixupGoal(_currentRequest);

                if (_currentRequest.pathFinderOptions.usePathSmoothing)
                {
                    path = _smoother.Smooth(_goal, maxPathLength, _currentRequest, _cellCostStrategy);
                }
                else
                {
                    path = new Path(maxPathLength);

                    //Push the actual end position as the goal
                    path.Push(new Position(_currentRequest.to));

                    IPathNode current = _goal.predecessor;
                    while (current != null)
                    {
                        path.Push(current);
                        current = current.predecessor;
                    }

                    //Instead of testing for it in the while loop, just pop off the start node and replace it with the actual start position
                    if (path.count > 1)
                    {
                        path.Pop();
                    }

                    path.Push(new Position(_currentRequest.from));
                }

                result = new PathResult(status, path, _goal.g, _currentRequest);
            }
            else
            {
                result = new PathResult(status, null, 0, _currentRequest);
            }

            _currentRequest.Complete(result);
            _currentRequest = null;
        }
        private void ConsumePath()
        {
            PathResult result = _pendingResult;
            _pendingResult = null;

            var req = result.originalRequest as InternalPathRequest;

            //Consume way points if appropriate. This must be done prior to the processing of the result, since if the request was a way point request, the first item in line is the one the result concerns.
            if (req.pathType == InternalPathRequest.Type.Waypoint)
            {
                AnnounceEvent(UnitNavigationEventMessage.Event.WaypointReached, _wayPoints.Dequeue(), null);
            }

            //Process the result
            if (!ProcessAndValidateResult(result))
            {
                return;
            }

            _currentPath = result.path;

            // If we have a formation we want to recalculate positions
            // We turn the model unit to face the new path direction so the formation can be sorted right away.
            if (_currentFormation != null)
            {
                _modelUnit.transform.LookAt(_currentPath[1].position);
                SetFormation(_currentFormation);
            }

            SetVectorFieldPath();
        }
        void INeedPath.ConsumePathResult(PathResult result)
        {
            // Execute on the main thread to avoid multi-threading issues or the need for using a lock or Monitor
            NavLoadBalancer.marshaller.ExecuteOnMainThread(() =>
            {
                // If we have stopped or get back the result of a request other than the one we currently expect, just toss it as it will be outdated.
                if (result.originalRequest != _pendingPathRequest)
                {
                    return;
                }

                _pendingResult = result;
                _pendingPathRequest = null;
            });
        }
        private bool ConsumeResult()
        {
            //Since result processing may actually repath and consequently a new result may arrive we need to operate on locals and null the pending result
            PathResult result;
            lock (_syncLock)
            {
                result = _pendingResult;
                _pendingResult = null;
            }

            var req = result.originalRequest as InternalPathRequest;

            //Consume way points if appropriate. This must be done prior to the processing of the result, since if the request was a way point request, the first item in line is the one the result concerns.
            if (req.pathType == InternalPathRequest.Type.Waypoint)
            {
                _wayPoints.Dequeue();
            }
            else if (req.pathType == InternalPathRequest.Type.PathboundWaypoint)
            {
                _pathboundWayPoints.Dequeue();
            }

            //Reset current destination and path no matter what
            _previousDestination = _transform.position;
            _currentDestination = null;
            _currentPath = null;

            //Process the result
            if (!ProcessAndValidateResult(result))
            {
                return false;
            }

            //Consume the result
            _onFinalApproach = false;
            _currentPath = result.path;
            _currentGrid = req.fromGrid;
            _remainingSquaredDistance = _currentPath.CalculateSquaredLength();
            _endOfResolvedPath = _currentPath.Last().position;
            _endOfPath = _endOfResolvedPath;

            //Update pending way points
            UpdatePathboundWaypoints(result.pendingWaypoints);

            //Pop the first node as our next destination.
            _unit.hasArrivedAtDestination = false;
            _currentDestination = _currentPath.Pop();
            return true;
        }
Example #19
0
 void INeedPath.ConsumePathResult(PathResult result)
 {
     LoadBalancer.marshaller.ExecuteOnMainThread(() => _callback(result));
 }
Example #20
0
        private bool ProcessAndValidateResult(PathResult result)
        {
            for (int i = 0; i < _resultProcessors.Length; i++)
            {
                if (_resultProcessors[i].HandleResult(result, this))
                {
                    return (result.status == PathingStatus.Complete);
                }
            }

            UnitNavigationEventMessage.Event msgEvent = UnitNavigationEventMessage.Event.None;

            switch (result.status)
            {
                case PathingStatus.Complete:
                {
                    /* All is good, no more to do */
                    return true;
                }

                case PathingStatus.NoRouteExists:
                {
                    msgEvent = UnitNavigationEventMessage.Event.StoppedNoRouteExists;
                    break;
                }

                case PathingStatus.DestinationBlocked:
                {
                    msgEvent = UnitNavigationEventMessage.Event.StoppedDestinationBlocked;
                    break;
                }

                case PathingStatus.Decayed:
                {
                    //We cannot reissue the request here, since we may be on a different thread, but then again why would we issue the request again if it had a decay threshold its no longer valid.
                    msgEvent = UnitNavigationEventMessage.Event.StoppedRequestDecayed;
                    break;
                }

                case PathingStatus.StartOutsideGrid:
                case PathingStatus.EndOutsideGrid:
                case PathingStatus.Failed:
                {
                    //The first two are handled before going to the pather, by the DirectPather, and since it would be a bug if either happen and not something a handler should care for
                    //we do not send a message
                    Debug.LogError("Unexpected status returned from pather: " + result.status.ToString());
                    break;
                }
            }

            var destination = result.originalRequest.to;
            var pendingWaypoints = _wayPoints.ToArray();

            StopInternal();

            if (msgEvent != UnitNavigationEventMessage.Event.None)
            {
                AnnounceEvent(msgEvent, destination, pendingWaypoints);
            }

            return false;
        }
Example #21
0
 /// <summary>
 /// Completes this request
 /// </summary>
 /// <param name="result">The result.</param>
 void IPathRequest.Complete(PathResult result)
 {
     this.requester.ConsumePathResult(result);
 }
Example #22
0
 public void Complete(PathResult result)
 {
     throw new InvalidOperationException();
 }
        private void ConsumeResult()
        {
            //Since result processing may actually repath and consequently a new result may arrive we need to operate on locals and null the pending result
            PathResult result;
            lock (_syncLock)
            {
                result = _pendingResult;
                _pendingResult = null;
            }

            var req = result.originalRequest as InternalPathRequest;

            //Consume way points if appropriate. This must be done prior to the processing of the result, since if the request was a way point request, the first item in line is the one the result concerns.
            bool isWaypoint = req.pathType == InternalPathRequest.Type.Waypoint;
            if (!isWaypoint)
            {
                //Since a waypoint request does not account for the entire path, we do not set the request time
                _lastPathRequestTime = req.timeStamp;
            }

            //Process the result
            if (ProcessAndValidateResult(result, isWaypoint))
            {
                //Consume the result
                SetPath(result.path, isWaypoint);
            }
        }
Example #24
0
 //INeedPath
 public virtual void ConsumePathResult(PathResult result)
 {
     Debug.LogWarning("Received path " + result);
     //throw new NotImplementedException();
 }
 private void StopInternal()
 {
     lock (_syncLock)
     {
         _stopped = true;
         _wayPoints.Clear();
         _currentPath = null;
         _pendingPathRequest = null;
         _currentDestination = null;
         _pendingResult = null;
         _manualReplan = null;
     }
 }
Example #26
0
        private void ConsumeResult()
        {
            //Consume way points if appropriate. This must be done prior to the processing of the result, since if the request was a way point request, the first item in line is the one the result concerns.
            if (_pendingResult.originalRequest.type == RequestType.Waypoint)
            {
                _wayPoints.Dequeue();
            }
            else if (_pendingResult.originalRequest.type == RequestType.PathboundWaypoint)
            {
                _pathboundWayPoints.Dequeue();
            }

            //Reset current destination no matter what
            _currentDestination = null;

            //Since result processing may actually repath and consequently a new result may arrive we need to operate on locals and null the pending result
            var result = _pendingResult;
            _pendingResult = null;

            //Process the result
            if (!ProcessAndValidateResult(result))
            {
                return;
            }

            //Consume the result
            _currentPath = result.path;
            _currentGrid = result.originalRequest.fromGrid;
            _endOfResolvedPath = _currentPath.Last().position;
            _endOfPath = _endOfResolvedPath;

            //Update pending way points
            UpdatePathboundWaypoints(result.pendingWaypoints);

            //The first point on the path is always the origin of the request, so we want to skip that.
            _currentPath.Pop();
        }