예제 #1
0
        /// <summary>
        /// Generates a detour that avoids the obstacle that was found by the provided entryRay and hit.
        /// </summary>
        /// <param name="entryRay">The ray used to find the entryPt.</param>
        /// <param name="entryHit">The info for the entryHit.</param>
        /// <returns></returns>
        private INavigableTarget GenerateDetourAroundObstacle(Ray entryRay, RaycastHit entryHit) {
            INavigableTarget detour = null;
            Transform obstacle = entryHit.transform;
            string obstacleName = obstacle.parent.name + "." + obstacle.name;
            Vector3 rayEntryPoint = entryHit.point;
            SphereCollider obstacleCollider = entryHit.collider as SphereCollider;
            float obstacleRadius = obstacleCollider.radius;
            float rayLength = (2F * obstacleRadius) + 1F;
            Vector3 pointBeyondKeepoutZone = entryRay.GetPoint(entryHit.distance + rayLength);
            Vector3 rayExitPoint = FindRayExitPoint(entryRay, entryHit, pointBeyondKeepoutZone, 0);

            //D.Log("{0} found RayExitPoint. EntryPt to exitPt distance = {1}.", Name, Vector3.Distance(rayEntryPoint, rayExitPoint));
            Vector3 obstacleCenter = obstacle.position;
            var ptOnSphere = UnityUtility.FindClosestPointOnSphereOrthogonalToIntersectingLine(rayEntryPoint, rayExitPoint, obstacleCenter, obstacleRadius);
            float obstacleClearanceLeeway = 2F; // HACK
            var detourWorldSpaceLocation = ptOnSphere + (ptOnSphere - obstacleCenter).normalized * obstacleClearanceLeeway;

            INavigableTarget obstacleParent = obstacle.gameObject.GetSafeFirstInterfaceInParents<INavigableTarget>();
            D.Assert(obstacleParent != null, "Obstacle {0} does not have a {1} parent.".Inject(obstacleName, typeof(INavigableTarget).Name));

            if (obstacleParent.IsMobile) {
                var detourRelativeToObstacleCenter = detourWorldSpaceLocation - obstacleCenter;
                var detourRef = new Reference<Vector3>(() => obstacle.position + detourRelativeToObstacleCenter);
                detour = new MovingLocation(detourRef);
            }
            else {
                detour = new StationaryLocation(detourWorldSpaceLocation);
            }

            //D.Log("{0} found detour {1} to avoid obstacle {2} at {3}. \nDistance to detour = {4:0.#}. Obstacle keepout radius = {5:0.##}. Detour is {6:0.#} from obstacle center.",
            //Name, detour.FullName, obstacleName, obstacleCenter, Vector3.Distance(Position, detour.Position), obstacleRadius, Vector3.Distance(obstacleCenter, detour.Position));
            return detour;
        }
예제 #2
0
 /// <summary>
 /// Generates a detour around the provided obstacle.
 /// </summary>
 /// <param name="obstacle">The obstacle.</param>
 /// <param name="hitInfo">The hit information.</param>
 /// <param name="fleetRadius">The fleet radius.</param>
 /// <returns></returns>
 private AutoPilotDestinationProxy GenerateDetourAroundObstacle(IAvoidableObstacle obstacle, RaycastHit hitInfo, float fleetRadius) {
     Vector3 detourPosition = obstacle.GetDetour(Position, hitInfo, fleetRadius);
     StationaryLocation detour = new StationaryLocation(detourPosition);
     Vector3 detourOffset = CalcDetourOffset(detour);
     float tgtStandoffDistance = _ship.CollisionDetectionZoneRadius;
     return detour.GetApMoveTgtProxy(detourOffset, tgtStandoffDistance, Position);
 }
예제 #3
0
 /// <summary>
 /// Refreshes the course.
 /// </summary>
 /// <param name="mode">The mode.</param>
 /// <param name="wayPtProxy">The optional waypoint. When not null, this is always a StationaryLocation detour to avoid an obstacle.</param>
 /// <exception cref="System.NotImplementedException"></exception>
 private void RefreshCourse(CourseRefreshMode mode, AutoPilotDestinationProxy wayPtProxy = null) {
     //D.Log(ShowDebugLog, "{0}.RefreshCourse() called. Mode = {1}. CourseCountBefore = {2}.", DebugName, mode.GetValueName(), AutoPilotCourse.Count);
     switch (mode) {
         case CourseRefreshMode.NewCourse:
             D.AssertNull(wayPtProxy);
             ApCourse.Clear();
             ApCourse.Add(_ship);
             IShipNavigable courseTgt;
             if (ApTargetProxy.IsMobile) {
                 courseTgt = new MobileLocation(new Reference<Vector3>(() => ApTargetProxy.Position));
             }
             else {
                 courseTgt = new StationaryLocation(ApTargetProxy.Position);
             }
             ApCourse.Add(courseTgt);  // includes fstOffset
             break;
         case CourseRefreshMode.AddWaypoint:
             ApCourse.Insert(ApCourse.Count - 1, new StationaryLocation(wayPtProxy.Position));    // changes Course.Count
             break;
         case CourseRefreshMode.ReplaceObstacleDetour:
             D.AssertEqual(3, ApCourse.Count);
             ApCourse.RemoveAt(ApCourse.Count - 2);          // changes Course.Count
             ApCourse.Insert(ApCourse.Count - 1, new StationaryLocation(wayPtProxy.Position));    // changes Course.Count
             break;
         case CourseRefreshMode.RemoveWaypoint:
             D.AssertEqual(3, ApCourse.Count);
             bool isRemoved = ApCourse.Remove(new StationaryLocation(wayPtProxy.Position));     // Course.RemoveAt(Course.Count - 2);  // changes Course.Count
             D.Assert(isRemoved);
             break;
         case CourseRefreshMode.ClearCourse:
             D.AssertNull(wayPtProxy);
             ApCourse.Clear();
             break;
         default:
             throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(mode));
     }
     //D.Log(ShowDebugLog, "CourseCountAfter = {0}.", Course.Count);
     HandleCourseChanged();
 }
예제 #4
0
 /// <summary>
 /// Calculates and returns the world space offset to the provided detour that when combined with the
 /// detour's position, represents the actual location in world space this ship is trying to reach, 
 /// aka DetourPoint. Used to keep ships from bunching up at the detour when many ships in a fleet encounter the same obstacle.
 /// </summary>
 /// <param name="detour">The detour.</param>
 /// <returns></returns>
 private Vector3 CalcDetourOffset(StationaryLocation detour) {
     if (_isApFleetwideMove) {
         // make separate detour offsets as there may be a lot of ships encountering this detour
         Quaternion shipCurrentRotation = _ship.transform.rotation;
         Vector3 shipToDetourDirection = (detour.Position - _ship.Position).normalized;
         Quaternion shipRotationChgReqdToFaceDetour = Quaternion.FromToRotation(_ship.CurrentHeading, shipToDetourDirection);
         Quaternion shipRotationThatFacesDetour = Math3D.AddRotation(shipCurrentRotation, shipRotationChgReqdToFaceDetour);
         Vector3 shipLocalFormationOffset = _ship.FormationStation.LocalOffset;
         Vector3 detourWorldSpaceOffset = Math3D.TransformDirectionMath(shipRotationThatFacesDetour, shipLocalFormationOffset);
         return detourWorldSpaceOffset;
     }
     return Vector3.zero;
 }
예제 #5
0
 public TargetInfo(StationaryLocation sl, Vector3 fstOffset, float fullSpeed) {
     Target = sl;
     Destination = sl.Position + fstOffset;
     CloseEnoughDistance = fullSpeed * 0.5F;
     CloseEnoughDistanceSqrd = CloseEnoughDistance * CloseEnoughDistance;
 }
예제 #6
0
 /// <summary>
 /// Plots a course to a stationary location and notifies the requester of the 
 /// outcome via the onCoursePlotCompleted event.
 /// </summary>
 /// <param name="location">The stationary location.</param>
 /// <param name="speed">The speed.</param>
 /// <param name="isFleetMove">if set to <c>true</c> this navigator will only move when the fleet is ready.</param>
 private void PlotCourse(StationaryLocation location, Speed speed, bool isFleetMove) {
     // a formationOffset is required if this is a fleet move
     Vector3 destinationOffset = isFleetMove ? _data.FormationStation.StationOffset : Vector3.zero;
     _targetInfo = new TargetInfo(location, destinationOffset, _data.FullStlSpeed);
     Speed = speed;
     _isFleetMove = isFleetMove;
     PlotCourse();
 }
예제 #7
0
 private void AssessNeedForRepair() {
     if (Data.Health < 0.30F) {
         if (CurrentOrder == null || CurrentOrder.Directive != ShipDirective.Repair) {
             var repairLoc = Data.Position - _transform.forward * 10F;
             INavigableTarget repairDestination = new StationaryLocation(repairLoc);
             OverrideCurrentOrder(ShipDirective.Repair, retainSuperiorsOrder: true, target: repairDestination);
         }
     }
 }
예제 #8
0
 public ShipDestinationInfo(StationaryLocation location, Vector3 fstOffset, Reference<float> distanceTraveledInOneHour) {
     Target = location;
     _fstOffset = fstOffset;
     _closeEnoughDistanceRef = distanceTraveledInOneHour;
     _progressCheckDistanceRef = distanceTraveledInOneHour;
 }