Пример #1
0
        //额外辅助方法部分,暂定到达目标就算停止
        public bool IsAtDestination()
        {
            //原作中crowd用2D做检查,simple用3D做检查。
            //这目前来看似乎没什么道理,所以索性整合在一起做一个方法,还可以返回给上层UnityAgent用
            bool    Check3D = Vector3Util.SloppyEquals(desiredPosition.point, plannerGoal.point, 0.005f);
            Vector3 pos     = desiredPosition.point;
            Vector3 goal    = plannerGoal.point;
            bool    Check2D = Vector2Util.SloppyEquals(new Vector2(pos.x, pos.z), new Vector2(goal.x, goal.z), 0.005f);

            return(Check3D | Check2D);
        }
Пример #2
0
        /// <summary>
        /// Returns the normalized vector that is perpendicular to line AB. (Costly method!)
        /// </summary>
        /// <remarks>
        /// <para>
        /// The direction of the vector will be to the right when viewed from point A to point B
        /// along the line.
        /// </para>
        /// <para>
        /// Special Case: A zero length vector will be returned if the points are collocated.
        /// </para>
        /// </remarks>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on line AB.</param>
        /// <returns>
        /// The normalized vector that is perpendicular to line AB, or a zero length vector if the
        /// points are collocated.
        /// </returns>
        public static Vector2 GetNormalAB(Vector2 a, Vector2 b)
        {
            if (Vector2Util.SloppyEquals(a, b, MathUtil.Tolerance))
            {
                // Points do not form a line.
                return(new Vector2());
            }

            Vector2 result = Vector2Util.GetDirectionAB(a, b);

            float origX = result.x;

            result.x = result.y;
            result.y = -origX;

            return(result);
        }
Пример #3
0
        /// <summary>
        /// Update the planner.
        /// </summary>
        /// <returns>True if successful.</returns>
        public bool Update()
        {
            if (mAtGoalState == StateNormal)
            {
                agent.SyncCrowdToDesired();
            }

            bool newPos  = (agent.data.flags & NavFlag.HasNewPosition) != 0;
            bool newGoal = (agent.data.flags & NavFlag.HasNewGoal) != 0;

            NavmeshPoint pt;

            if (newPos)
            {
                pt = agent.GetPointSearch(agent.data.position);
                if (pt.polyRef == 0)
                {
                    // Ignore new position.
                    Debug.LogWarning(string.Format(
                                         "{0}: Could not constrain new position to the navigation mesh. Ignoring: {1}"
                                         , agent.transform.name, pt.ToString()));

                    newPos = false;
                }
                else
                {
                    agent.data.desiredPosition = pt;
                }
            }

            if (newGoal)
            {
                pt = agent.GetPointSearch(agent.data.goal);
                if (pt.polyRef == 0)
                {
                    // Ignore new goal.
                    Debug.LogWarning(string.Format(
                                         "{0}: Could not constrain new goal to the navigation mesh. Ignoring: {1}"
                                         , agent.transform.name, pt.ToString()));

                    newGoal = false;
                }
                else
                {
                    agent.data.plannerGoal = pt;
                }
            }

            if (mAtGoalState != StateNormal && newGoal || newPos)
            {
                TransitionToNormalGoalState();
            }

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

            if (newPos)
            {
                // Note: This call inherently handles everything, not just the
                // position change.
                return(HandlePositionFeedback());
            }

            if (!HandleNormalPlanning(newGoal))
            {
                // A critical failure has occurred.
                return(false);
            }

            if ((agent.data.flags & NavFlag.CrowdConfigUpdated) != 0)
            {
                CrowdAgentParams config = agent.crowdConfig;

                if (mAtGoalState != StateNormal)
                {
                    config.maxSpeed = 0;
                }

                agent.crowdAgent.SetConfig(config);
                agent.data.flags &= ~NavFlag.CrowdConfigUpdated;
            }

            if (mAtGoalState == StateInRange)
            {
                // Need to manually move the agent to the goal.
                Vector3 pos  = agent.data.desiredPosition.point;
                Vector3 goal = agent.data.plannerGoal.point;

                if (Vector2Util.SloppyEquals(
                        new Vector2(pos.x, pos.z), new Vector2(goal.x, goal.z), 0.005f))
                {
                    // Snap to the goal and, essentially, go into an idle
                    // state.
                    mAtGoalState = StateIdle;
                    agent.data.desiredPosition = agent.data.plannerGoal;
                    agent.data.desiredSpeedSq  = 0;
                    agent.data.desiredVelocity = Vector3.zero;

                    // Debug.Log("Reached goal.  Going idle.");
                }
                else
                {
                    // Need to manually move the agent to the goal.
                    // Assumptions: The distance is short, and the crowd has
                    // already slowed the agent's speed to a minimal value.

                    float desiredSpeed = Mathf.Sqrt(agent.data.desiredSpeedSq);

                    agent.data.desiredPosition.point =
                        Vector3.MoveTowards(pos, goal, desiredSpeed * Time.deltaTime);

                    // While the point will be on the mesh surface, we
                    // can't assume we are already in the goal's polygon.
                    agent.data.desiredPosition.polyRef = 0;

                    agent.data.desiredVelocity =
                        (agent.data.desiredPosition.point - pos).normalized * desiredSpeed;
                }
            }

            return(true);
        }