Beispiel #1
0
        /// <summary>
        /// Instructs a Vehicle Entity to follow a defined path (pathway), within the defined predicted timeframe
        /// </summary>
        /// <param name="vehicle"></param>
        /// <param name="direction"></param>
        /// <param name="predictionTime"></param>
        /// <param name="path"></param>
        /// <returns>The Vector to move to</returns>
        public static Vector3 FollowPath(VehicleActor vehicle, int direction, float predictionTime, Pathway path)
        {
            // our goal will be offset from our path distance by this amount
            float pathDistanceOffset = direction * predictionTime * vehicle.Velocity;

            // predict our future position
            Vector3 futurePosition = vehicle.PredictFuturePosition(predictionTime);

            // measure distance along path of our current and predicted positions
            float nowPathDistance    = path.MapPointToPathDistance(vehicle.Position);
            float futurePathDistance = path.MapPointToPathDistance(futurePosition);

            // are we facing in the correction direction?
            bool rightway = ((pathDistanceOffset > 0) ?
                             (nowPathDistance < futurePathDistance) :
                             (nowPathDistance > futurePathDistance));

            // find the point on the path nearest the predicted future position
            // XXX need to improve calling sequence, maybe change to return a
            // XXX special path-defined object which includes two Vector3s and a
            // XXX bool (onPath,tangent (ignored), withinPath)
            Vector3 tangent;
            float   outside;
            Vector3 onPath = path.MapPointToPath(futurePosition, out tangent, out outside);

            // no steering is required if (a) our future position is inside
            // the path tube and (b) we are facing in the correct direction
            if ((outside < 0) && rightway)
            {
                // all is well, return zero steering
                return(Vector3.Zero);
            }
            else
            {
                // otherwise we need to steer towards a target point obtained
                // by adding pathDistanceOffset to our current path position

                float   targetPathDistance = nowPathDistance + pathDistanceOffset;
                Vector3 target             = path.MapPathDistanceToPoint(targetPathDistance);

                //log PathFollowing(futurePosition, onPath, target, outside);

                // return steering to seek target on path
                return(Seek(vehicle, target));
            }
        }
Beispiel #2
0
    /// <summary>
    /// Should the force be calculated?
    /// </summary>
    /// <returns>
    /// A <see cref="Vector3"/>
    /// </returns>
    protected override Vector3 CalculateForce()
    {
        if (_path == null || _path.SegmentCount < 2)
        {
            return(Vector3.zero);
        }

        // our goal will be offset from our path distance by this amount
        float pathDistanceOffset = (int)_direction * _predictionTime * Vehicle.Speed;

        // predict our future position
        Vector3 futurePosition = Vehicle.PredictFuturePosition(_predictionTime);

        // measure distance along path of our current and predicted positions
        float nowPathDistance    = _path.MapPointToPathDistance(Vehicle.Position);
        float futurePathDistance = _path.MapPointToPathDistance(futurePosition);

        // are we facing in the correction direction?
        bool rightway = ((pathDistanceOffset > 0) ? (nowPathDistance < futurePathDistance) : (nowPathDistance > futurePathDistance));

        // find the point on the path nearest the predicted future position
        var tStruct = new PathRelativePosition();

        _path.MapPointToPath(futurePosition, ref tStruct);


        // no steering is required if (a) our future position is inside
        // the path tube and (b) we are facing in the correct direction
        if ((tStruct.outside < 0) && rightway)
        {
            // TODO Evaluate. This assumes the vehicle has inertia, and would stop if inside the path tube
            return(Vector3.zero);
        }
        else
        {
            /*
             * Otherwise we need to steer towards a target point obtained
             * by adding pathDistanceOffset to our current path position.
             *
             * Notice that this method does not steer for the point in the
             * path that is closest to our future position, which is why
             * the return value of MapPointToPath is ignored above. Instead,
             * it estimates how far the vehicle will move in units, and then
             * aim for the point in the path that is that many units away
             * from our current path position _in path length_.   This means
             * that it adds up the segment lengths and aims for the point
             * that is N units along the length of the path, which can imply
             * bends and turns and is not a straight vector projected away
             * from our position.
             *
             * This also means that having too high a prediction time will
             * have the effect of the agent seemingly approaching the path
             * in an elliptical manner.
             */
            float targetPathDistance = nowPathDistance + pathDistanceOffset;
            var   target             = _path.MapPathDistanceToPoint(targetPathDistance);

            // return steering to seek target on path
            var seek = Vehicle.GetSeekVector(target);
            return(seek);
        }
    }