Example #1
0
        /// <summary>
        /// Update the mover.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method will never fail.
        /// </para>
        /// <para>
        /// With the exception of forced moves, updates will temporarily halt during planner
        /// failure.
        /// </para>
        /// </remarks>
        /// <returns>True. (Never returns false.)</returns>
        public bool Update()
        {
            Transform trans = agent.transform;

            if ((agent.data.flags & NavFlag.ForceMove) != 0)
            {
                agent.data.position = agent.data.goal;

                if ((agent.data.flags & NavFlag.GoalRotationEnabled) != 0)
                {
                    agent.data.rotation = agent.data.goalRotation;
                }

                agent.transform.position = agent.data.position.point;
                agent.transform.rotation = agent.data.rotation;

                agent.data.flags =
                    (agent.data.flags | NavFlag.HasNewPosition) & ~NavFlag.ForceMove;

                Debug.Log(agent.transform.name + ": Force Move");
                return(true);
            }

            // Note: Keep this after the force move handling.
            if ((agent.data.flags & NavFlag.PlannerFailed) != 0)
            {
                // Planner has failed. Early exit.
                return(true);
            }

            agent.data.position = agent.data.desiredPosition;
            trans.position      = agent.data.position.point;

            Quaternion rotation = agent.data.rotation;

            if ((agent.data.flags & NavFlag.GoalRotationEnabled) != 0 &&
                agent.IsNear(agent.data.position.point, agent.data.goal.point))
            {
                // Close to goal.  So use the goal rotation.
                rotation = agent.data.goalRotation;
            }
            else if (agent.data.desiredSpeedSq > agent.agentGroup.turnThreshold)
            {
                // Agent is not near the goal, so use the planner's rotation.
                // The conditional test prevents unnecessary seeking
                // at low speeds.
                rotation = Quaternion.LookRotation(
                    new Vector3(agent.data.desiredVelocity.x, 0, agent.data.desiredVelocity.z));
            }

            trans.rotation = Quaternion.Slerp(
                trans.rotation, rotation, Time.deltaTime * agent.agentGroup.maxTurnSpeed);

            agent.data.rotation = trans.rotation;

            return(true);
        }
Example #2
0
        /// <summary>
        /// Manages the crowd agent target, replanning the long distance path if needed.
        /// </summary>
        /// <returns>False on critical failure.</returns>
        private bool HandleNormalPlanning(bool hasNewGoal)
        {
            // Re-targetting will only occur if there is a new goal or getting close to an
            // intermediate target.

            if (hasNewGoal ||
                !mGoalInRange && agent.IsNear(agent.data.desiredPosition.point, mTarget.point))
            {
                // First try to set the target without replanning.
                if (!SetLocalTarget())
                {
                    // This can happen when approaching the target from
                    // outside the planned path, which can happen when
                    // the crowd manager takes a different path.
                    // (Or a new goal was set.)

                    if (agent.PlanPath(agent.data.desiredPosition, agent.data.plannerGoal) <= 0)
                    {
                        // Critical failure.
                        Debug.LogError(string.Format(
                                           "{0}: Path replan failed. Position: {1}, Goal: {2}"
                                           , agent.transform.name
                                           , agent.data.desiredPosition.ToString()
                                           , agent.data.plannerGoal.ToString()));
                        return(false);
                    }

                    // Next call should not not fail since the path is known to be good.
                    return(SetLocalTarget());
                }
            }
            else if (mGoalInRange)
            {
                /*
                 * Need to monitor to see if the goal has been reached.  This can be tricky.
                 * The optimal 'at' and 'near' range ranges are usually too restrictive and too
                 * large respectively. So a fixed value, based on experience, is used instead.
                 * (OK to make this value configurable.)
                 *
                 * Assumption: Other parts of the code detect if a re-evaluation of position
                 * is needed.
                 */
                if (mAtGoalState == StateNormal)
                {
                    if (Vector3Util.IsInRange(agent.data.desiredPosition.point
                                              , agent.data.plannerGoal.point
                                              , 0.12f, agent.data.heightTolerence))
                    {
                        // Remove from the crowd and add back, exactly at the goal with a zero max
                        // speed.  Basically, puts a static obstacle into the crowd.

                        mAtGoalState = StateInRange;
                        agent.RemoveFromCrowd();

                        CrowdAgentParams config = agent.crowdConfig;
                        config.maxSpeed = 0;

                        agent.crowdAgent =
                            agent.navGroup.crowd.AddAgent(agent.data.plannerGoal.point, config);

                        agent.data.flags &= ~NavFlag.CrowdConfigUpdated;

                        // Debug.Log("Transition to 'at goal' task.");
                    }
                }
            }
            return(true);
        }