Exemplo n.º 1
0
        public virtual void UpdateAi()
        {
            // reset our inputs
            Horz = 0;
            Vert = 0;

            var obstacleFinderResult = IsObstacleAhead();

            switch (CurrentAiState)
            {
            // -----------------------------
            case AIState.MovingLookingForTarget:
                // look for chase target
                if (FollowTarget != null)
                {
                    LookAroundFor(FollowTarget);
                }

                // the AvoidWalls function looks to see if there's anything in-front. If there is,
                // it will automatically change the value of moveDirection before we do the actual move
                if (obstacleFinderResult == 1)
                {     // GO LEFT
                    SetAiState(AIState.StoppedTurningLeft);
                }
                if (obstacleFinderResult == 2)
                {     // GO RIGHT
                    SetAiState(AIState.StoppedTurningRight);
                }

                if (obstacleFinderResult == 3)
                {     // BACK UP
                    SetAiState(AIState.BackingUpLookingForTarget);
                }

                // all clear! head forward
                MoveForward();
                break;

            case AIState.ChasingTarget:
                // chasing
                // in case mode, we point toward the target and go right at it!

                // quick check to make sure that we have a target (if not, we drop back to patrol mode)
                if (FollowTarget == null)
                {
                    SetAiState(AIState.MovingLookingForTarget);
                }

                // the TurnTowardTarget function does just that, so to chase we just throw it the current target
                TurnTowardTarget(FollowTarget);

                // find the distance between us and the chase target to see if it is within range
                _distanceToChaseTarget = Vector3.Distance(MyTransform.position, FollowTarget.position);

                // check the range
                if (_distanceToChaseTarget > MinChaseDistance)
                {
                    // keep charging forward
                    MoveForward();
                }

                // here we do a quick check to test the distance between AI and target. If it's higher than
                // our maxChaseDistance variable, we drop out of chase mode and go back to patrolling.
                if (_distanceToChaseTarget > MaxChaseDistance || CanSee(FollowTarget) == false)
                {
                    // set our state to 1 - moving_looking_for_target
                    SetAiState(AIState.MovingLookingForTarget);
                }

                break;
            // -----------------------------

            case AIState.BackingUpLookingForTarget:

                // look for chase target
                if (FollowTarget != null)
                {
                    LookAroundFor(FollowTarget);
                }

                // backing up
                MoveBack();

                if (obstacleFinderResult == 0)
                {
                    // now we've backed up, lets randomize whether to go left or right
                    if (Random.Range(0, 100) > 50)
                    {
                        SetAiState(AIState.StoppedTurningLeft);
                    }
                    else
                    {
                        SetAiState(AIState.StoppedTurningRight);
                    }
                }

                break;

            case AIState.StoppedTurningLeft:
                // look for chase target
                if (FollowTarget != null)
                {
                    LookAroundFor(FollowTarget);
                }

                // stopped, turning left
                TurnLeft();

                if (obstacleFinderResult == 0)
                {
                    SetAiState(AIState.MovingLookingForTarget);
                }
                break;

            case AIState.StoppedTurningRight:
                // look for chase target
                if (FollowTarget != null)
                {
                    LookAroundFor(FollowTarget);
                }

                // stopped, turning right
                TurnRight();


                // check results from looking, to see if path ahead is clear
                if (obstacleFinderResult == 0)
                {
                    SetAiState(AIState.MovingLookingForTarget);
                }
                break;

            case AIState.PausedLookingForTarget:
                // standing still, with looking for chase target
                // look for chase target
                if (FollowTarget != null)
                {
                    LookAroundFor(FollowTarget);
                }
                break;

            case AIState.TranslateAlongWaypointPath:
                // following waypoints (moving toward them, not pointing at them) at the speed of
                // moveSpeed

                // make sure we have been initialized before trying to access waypoints
                if (!DidInit && !ReachedLastWaypoint)
                {
                    return;
                }

                UpdateWaypoints();

                // move the ship
                if (!IsStationary)
                {
                    _targetMoveVec = Vector3.Normalize(CurrentWaypointTransform.position - MyTransform.position);
                    _moveVec       = Vector3.Lerp(_moveVec, _targetMoveVec, Time.deltaTime * PathSmoothing);
                    MyTransform.Translate(_moveVec * MoveSpeed * Time.deltaTime);
                    MoveForward();

                    if (FaceWaypoints)
                    {
                        TurnTowardTarget(CurrentWaypointTransform);
                    }
                }
                break;

            case AIState.SteerToWaypoint:

                // make sure we have been initialized before trying to access waypoints
                if (!DidInit && !ReachedLastWaypoint)
                {
                    return;
                }

                UpdateWaypoints();

                if (CurrentWaypointTransform == null)
                {
                    // it may be possible that this function gets called before waypoints have been set up, so we catch any nulls here
                    return;
                }

                // now we just find the relative position of the waypoint from the car transform,
                // that way we can determine how far to the left and right the waypoint is.
                RelativeWaypointPosition = MyTransform.InverseTransformPoint(CurrentWaypointTransform.position);

                // by dividing the horz position by the magnitude, we get a decimal percentage of the turn angle that we can use to drive the wheels
                Horz = (RelativeWaypointPosition.x / RelativeWaypointPosition.magnitude);

                // now we do the same for torque, but make sure that it doesn't apply any engine torque when going around a sharp turn...
                if (Mathf.Abs(Horz) < 0.5f)
                {
                    Vert = RelativeWaypointPosition.z / RelativeWaypointPosition.magnitude - Mathf.Abs(Horz);
                }
                else
                {
                    NoMove();
                }
                break;

            case AIState.SteerToTarget:

                // make sure we have been initialized before trying to access waypoints
                if (!DidInit)
                {
                    return;
                }

                if (FollowTarget == null)
                {
                    // it may be possible that this function gets called before a targer has been set up, so we catch any nulls here
                    return;
                }

                // now we just find the relative position of the waypoint from the car transform,
                // that way we can determine how far to the left and right the waypoint is.
                RelativeWaypointPosition = transform.InverseTransformPoint(FollowTarget.position);

                // by dividing the horz position by the magnitude, we get a decimal percentage of the turn angle that we can use to drive the wheels
                Horz = (RelativeWaypointPosition.x / RelativeWaypointPosition.magnitude);

                // if we're outside of the minimum chase distance, drive!
                if (Vector3.Distance(FollowTarget.position, MyTransform.position) > MinChaseDistance)
                {
                    MoveForward();
                }
                else
                {
                    NoMove();
                }

                if (FollowTarget != null)
                {
                    LookAroundFor(FollowTarget);
                }

                // the AvoidWalls function looks to see if there's anything in-front. If there is,
                // it will automatically change the value of moveDirection before we do the actual move
                if (obstacleFinderResult == 1)
                {     // GO LEFT
                    TurnLeft();
                }

                if (obstacleFinderResult == 2)
                {     // GO RIGHT
                    TurnRight();
                }

                if (obstacleFinderResult == 3)
                {     // BACK UP
                    MoveBack();
                }

                break;

            case AIState.PausedNoTarget:
                // paused_no_target
                break;
            }
        }