Пример #1
0
        /// <summary>
        /// 检查和修复所有错误路径点
        /// </summary>
        /// <param name="sTri"></param>
        /// <param name="startPos"></param>
        /// <param name="eTri"></param>
        /// <param name="endPos"></param>
        /// <returns></returns>
        private PathResCode CheckAndFixPos(ref NavTriangle startTri, ref Vector2 startPos, ref NavTriangle endTri, ref Vector2 endPos)
        {
            if (startTri != null && endTri != null && startTri.GetGroupID() != endTri.GetGroupID())
            {
                return(PathResCode.GroupNotMatch);
            }

            if (endTri == null)
            {
                if (FixPos(ref endTri, ref endPos, startTri, startPos, END_POS_EXTEND_LENGTH) != PathResCode.Success)
                {
                    return(PathResCode.Failed);
                }
            }

            if (startTri == null)
            {
                PathResCode fixRet = FixPos(ref startTri, ref startPos, endTri, endPos, START_POS_EXTEND_LENGTH);
            }

            if (startTri == null || endTri == null)
            {
                return(PathResCode.Failed);
            }

            if (startTri.GetGroupID() != endTri.GetGroupID())
            {
                return(PathResCode.GroupNotMatch);
            }

            return(PathResCode.Success);
        }
Пример #2
0
		public NavTriangle CloneNavTriangle()
		{
			NavTriangle tri = new NavTriangle();
			//基础数据
			Array.Copy(this.m_vecPoints,tri.m_vecPoints,this.m_vecPoints.Length);  //三角形定点列表
			tri.m_iID = this.m_iID;  //三角形ID
			tri.m_iGroupID = this.m_iGroupID;   //三角形组ID
			Array.Copy( this.m_vecNeighbors , tri.m_vecNeighbors , this.m_vecNeighbors.Length);   //三角形邻居节点ID
			
			//计算数据
			tri.m_cCenter = this.m_cCenter;  //三角形中心点
			tri.m_cBoxCollider = this.m_cBoxCollider;    //三角形包围盒
			//tri.m_vecWallDistance = this.m_vecWallDistance;  //三角形相邻两边的中点距离
			Array.Copy(this.m_vecWallDistance , tri.m_vecWallDistance , this.m_vecWallDistance.Length);
			return tri;
		}
Пример #3
0
        /// <summary>
        /// 生成最终的路径点
        /// </summary>
        /// <param name="startPos">起始点</param>
        /// <param name="endPos">终点</param>
        /// <param name="triPathList">三角形路径列表</param>
        /// <param name="wayPoints">路径点</param>
        /// <param name="offSet">移动物体宽度</param>
        /// <returns></returns>
        private PathResCode CreateWayPoints(Vector2 startPos, Vector2 endPos
                                            , List <NavTriangle> triPathList, out List <Vector2> wayPoints, int offSet)
        {
            wayPoints = new List <Vector2>();
            if (triPathList.Count == 0 || startPos == null || endPos == null)
            {
                return(PathResCode.Failed);
            }

            // 保证从起点到终点的顺序
            triPathList.Reverse();

            // 保存出边编号
            for (int i = 0; i < triPathList.Count; i++)
            {
                NavTriangle tri = triPathList[i];
                if (i != triPathList.Count - 1)
                {
                    NavTriangle nextTri = triPathList[i + 1];
                    tri.SetOutWallIndex(tri.GetWallIndex(nextTri.GetID()));
                }
            }

            wayPoints.Add(startPos);

            //起点与终点在同一三角形中
            if (triPathList.Count == 1)
            {
                wayPoints.Add(endPos);
                return(PathResCode.Success);
            }

            WayPoint way = new WayPoint(startPos, triPathList[0]);

            while (!NMath.IsEqualZero(way.GetPoint() - endPos))
            {
                way = GetFurthestWayPoint(way, triPathList, endPos, offSet);
                if (way == null)
                {
                    return(PathResCode.CanNotGetNextWayPoint);
                }
                wayPoints.Add(way.GetPoint());
            }

            return(PathResCode.Success);
        }
Пример #4
0
        public NavTriangle CloneNavTriangle()
        {
            NavTriangle tri = new NavTriangle();

            //基础数据
            Array.Copy(this.m_vecPoints, tri.m_vecPoints, this.m_vecPoints.Length);          //三角形定点列表
            tri.m_iID      = this.m_iID;                                                     //三角形ID
            tri.m_iGroupID = this.m_iGroupID;                                                //三角形组ID
            Array.Copy(this.m_vecNeighbors, tri.m_vecNeighbors, this.m_vecNeighbors.Length); //三角形邻居节点ID

            //计算数据
            tri.m_cCenter      = this.m_cCenter;         //三角形中心点
            tri.m_cBoxCollider = this.m_cBoxCollider;    //三角形包围盒
            //tri.m_vecWallDistance = this.m_vecWallDistance;  //三角形相邻两边的中点距离
            Array.Copy(this.m_vecWallDistance, tri.m_vecWallDistance, this.m_vecWallDistance.Length);
            return(tri);
        }
Пример #5
0
        /// <summary>
        /// 根据f和h实现排序,A*算法
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private int CompareTriWithGValue(NavTriangle x, NavTriangle y)
        {
            double xFvalue = x.GetHValue() /*+ x.GValue*/;
            double yFvalue = y.GetHValue() /*+ y.GValue*/;

            if (xFvalue == yFvalue)
            {
                return(0);
            }
            else if (xFvalue < yFvalue)
            {
                return(1);
            }
            else
            {
                return(-1);
            }
        }
Пример #6
0
        /// <summary>
        /// Seek the specified sPos and ePos.
        /// </summary>
        /// <param name="sPos">S position.</param>
        /// <param name="ePos">E position.</param>
        public void Seek(Vector3 sPos, Vector3 ePos)
        {
            //
            List <NavTriangle> lst = new List <NavTriangle>();

            foreach (Triangle item in this.m_lstTriangle)
            {
                NavTriangle navTri = item.CloneNavTriangle();
                lst.Add(navTri);
                //Debug.Log( "src " + item.GetGroupID() + " :" + item.GetNeighbor(0)+"--" + item.GetNeighbor(1) + "--" + item.GetNeighbor(2) );
                //Debug.Log( "tar " + navTri.GetGroupID() + " :" + navTri.GetNeighbor(0)+"--" + navTri.GetNeighbor(1) + "--" + navTri.GetNeighbor(2) );
            }
            Seeker.GetInstance().NavMeshData = lst;
            List <Vector2> lstpath;
            Vector2        ssPos = new Vector2(sPos.x, sPos.z);
            Vector2        eePos = new Vector2(ePos.x, ePos.z);

            Seeker.GetInstance().Seek(ssPos, eePos, out lstpath, 1);
            //Debug.Log(lstpath.Count + " lstpath");
            this.m_lstFindPath = lstpath;
        }
Пример #7
0
        private NavTriangle m_cTriangle; //所在三角形

        public WayPoint(Vector2 pos, NavTriangle tri)
        {
            this.m_cPoint    = pos;
            this.m_cTriangle = tri;
        }
Пример #8
0
        /// <summary>
        /// 根据拐点计算法获得导航网格的下一个拐点
        /// </summary>
        /// <param name="way"></param>
        /// <param name="triPathList"></param>
        /// <param name="endPos"></param>
        /// <param name="offSet"></param>
        /// <returns></returns>
        private WayPoint GetFurthestWayPoint(WayPoint way, List <NavTriangle> triPathList, Vector2 endPos, int offSet)
        {
            WayPoint    nextWay = null;
            Vector2     currPnt = way.GetPoint();
            NavTriangle currTri = way.GetTriangle();
            NavTriangle lastTriA = currTri;
            NavTriangle lastTriB = currTri;
            int         startIndex = triPathList.IndexOf(currTri);            //开始路点所在的网格索引
            Line2D      outSide = currTri.GetSide(currTri.GetOutWallIndex()); //路径线在网格中的穿出边?
            Vector2     lastPntA = outSide.GetStartPoint();
            Vector2     lastPntB = outSide.GetEndPoint();
            Line2D      lastLineA = new Line2D(currPnt, lastPntA);
            Line2D      lastLineB = new Line2D(currPnt, lastPntB);
            Vector2     testPntA, testPntB;

            for (int i = startIndex + 1; i < triPathList.Count; i++)
            {
                currTri = triPathList[i];
                outSide = currTri.GetSide(currTri.GetOutWallIndex());
                if (i == triPathList.Count - 1)
                {
                    testPntA = endPos;
                    testPntB = endPos;
                }
                else
                {
                    testPntA = outSide.GetStartPoint();
                    testPntB = outSide.GetEndPoint();
                }

                if (lastPntA != testPntA)
                {
                    if (lastLineB.ClassifyPoint(testPntA) == PointSide.RIGHT_SIDE)
                    {
                        nextWay = new WayPoint(lastPntB, lastTriB);
                        return(nextWay);
                    }
                    else if (lastLineA.ClassifyPoint(testPntA) != PointSide.LEFT_SIDE)
                    {
                        lastPntA = testPntA;
                        lastTriA = currTri;
                        //重设直线
                        lastLineA = new Line2D(lastLineA.GetStartPoint(), lastPntA);
                    }
                }

                if (lastPntB != testPntB)
                {
                    if (lastLineA.ClassifyPoint(testPntB) == PointSide.LEFT_SIDE)
                    {
                        nextWay = new WayPoint(lastPntA, lastTriA);
                        return(nextWay);
                    }
                    else if (lastLineB.ClassifyPoint(testPntB) != PointSide.RIGHT_SIDE)
                    {
                        lastPntB = testPntB;
                        lastTriB = currTri;
                        //重设直线
                        lastLineB = new Line2D(lastLineB.GetStartPoint(), lastPntB);
                    }
                }
            }

            //到达终点
            nextWay = new WayPoint(endPos, triPathList[triPathList.Count - 1]);

            return(nextWay);
        }
Пример #9
0
        /// <summary>
        /// 根据原始点计算出正确的落在导航区内的位置,修复无效点和三角形
        /// </summary>
        /// <param name="orgTarTri">起源三角形</param>
        /// <param name="orgTarPos">起源点</param>
        /// <param name="otherTri">参考方向三角形</param>
        /// <param name="otherPos">参考方向点</param>
        /// <returns>结果</returns>
        private PathResCode FixPos(ref NavTriangle orgTarTri, ref Vector2 orgTarPos, NavTriangle otherTri, Vector2 otherPos, int extendLength)
        {
            Vector2 tarPos = orgTarPos;

            //////////////////////////////////////////////////////////////////////////
            //为了精确判断,需要逆向延长线段一定长度
            if (extendLength > 0)
            {
                Vector2 newTarPos = NMath.ExtendPos(otherPos, tarPos, extendLength);
                tarPos = newTarPos;
            }
            //////////////////////////////////////////////////////////////////////////

            Line2D linePath = new Line2D(tarPos, otherPos); //参考线段
            Rect   lineRect = NMath.LineRect(linePath);     //获取线段矩形包围盒

            //1)找到所有与参考线段矩形相交的三角形,并判断是否groupID相等
            List <NavTriangle> crossNavTris = new List <NavTriangle>();

            foreach (NavTriangle tri in this.m_lstTriangle)
            {
                if (NMath.CheckCross(lineRect, tri.GetBoxCollider()))
                {
                    if (otherTri != null && otherTri.GetGroupID() != tri.GetGroupID())
                    {
                        continue;
                    }
                    crossNavTris.Add(tri);
                }
            }

            //2)找出所有与参考线段相交的三角形,并记录相交点
            List <Vector2> crossPoints = new List <Vector2>(); //相交点列表
            List <int>     triIndex    = new List <int>();     //相交三角形索引列表

            for (int index = 0; index < crossNavTris.Count; index++)
            {
                NavTriangle crossTri = crossNavTris[index];
                Line2D      triLine;
                for (int i = 0; i < 3; i++)
                {
                    Vector2 insPoint;
                    triLine = new Line2D(crossTri.GetPoint(i), crossTri.GetPoint((i + 1) % 3));
                    if (linePath.Intersection(triLine, out insPoint) == LineCrossState.CROSS)
                    {
                        crossPoints.Add(insPoint);
                        triIndex.Add(index);
                    }
                }
            }

            if (crossPoints.Count == 0)
            {
                return(PathResCode.NoCrossPoint);
            }


            //3)找到最接近起源点的点
            Vector2 lastPos      = crossPoints[0];
            int     lastTriIndex = triIndex[0];
            double  lastLength   = Math.Pow(lastPos.x - orgTarPos.x, 2.0) + Math.Pow(lastPos.y - orgTarPos.y, 2.0);

            for (int i = 1; i < crossPoints.Count; i++)
            {
                double newLength = Math.Pow(crossPoints[i].x - orgTarPos.x, 2.0) + Math.Pow(crossPoints[i].y - orgTarPos.y, 2.0);
                if (newLength < lastLength)
                {
                    lastPos      = crossPoints[i];
                    lastTriIndex = triIndex[i];
                    lastLength   = newLength;
                }
            }

            //4)保存目标
            orgTarPos = lastPos;
            orgTarTri = crossNavTris[lastTriIndex];

            return(PathResCode.Success);
        }
Пример #10
0
        /// <summary>
        /// 寻路路径三角形
        /// </summary>
        /// <param name="strPos">起始点</param>
        /// <param name="endPos">终点</param>
        /// <param name="pathTriangle">输出三角形</param>
        /// <param name="offset">移动物品大小</param>
        /// <returns>结果</returns>
        private PathResCode SeekTrianglePath(ref Vector2 startPos, ref Vector2 endPos, out List <NavTriangle> pathList, int offset)
        {
            pathList = new List <NavTriangle>();
            NavTriangle startTri = null, endTri = null;

            //获得起始与终点三角形
            foreach (NavTriangle navTri in this.m_lstTriangle)
            {
                if (startTri == null)
                {
                    if (navTri.IsPointIn(startPos))
                    {
                        startTri = navTri;
                    }
                }

                if (endTri == null)
                {
                    if (navTri.IsPointIn(endPos))
                    {
                        endTri = navTri;
                    }
                }

                if (startTri != null && endTri != null)
                {
                    break;
                }
            }

            //检查和修复位置
            PathResCode posErr = CheckAndFixPos(ref startTri, ref startPos, ref endTri, ref endPos);

            if (posErr != PathResCode.Success)
            {
                return(posErr);
            }

            //////////////////////////////////// A*算法 ///////////////////////////////////////

            int  pathSessionId           = 1;
            bool foundPath               = false;
            List <NavTriangle> openList  = new List <NavTriangle>(); //开放列表
            List <NavTriangle> closeList = new List <NavTriangle>();

            startTri.SetSessionID(pathSessionId);

            openList.Add(startTri);
            while (openList.Count > 0)
            {
                // 1. 把当前节点从开放列表删除, 加入到封闭列表
                NavTriangle currNode;
                currNode = openList[openList.Count - 1];
                openList.Remove(currNode);
                closeList.Add(currNode);

                //已经找到目的地
                if (currNode.GetID() == endTri.GetID())
                {
                    foundPath = true;
                    break;
                }

                // 2. 对当前节点相邻的每一个节点依次执行以下步骤:
                // 遍历所有邻接三角型
                for (int i = 0; i < 3; i++)
                {
                    int         neighborID = currNode.GetNeighbor(i);
                    NavTriangle neighborTri;

                    // 3. 如果该相邻节点不可通行,则什么操作也不执行,继续检验下一个节点;
                    if (neighborID < 0)
                    {
                        //没有该邻居节点
                        continue;
                    }
                    else
                    {
                        neighborTri = this.m_lstTriangle[neighborID];

                        if (neighborTri == null || neighborTri.GetID() != neighborID)
                        {
                            return(PathResCode.NavIDNotMatch);
                        }
                    }
                    if (neighborTri.GetGroupID() == startTri.GetGroupID())
                    {
                        if (neighborTri.GetSessionID() != pathSessionId)
                        {
                            // 4. 如果该相邻节点不在开放列表中,则将该节点添加到开放列表中,
                            //    并将该相邻节点的父节点设为当前节点,同时保存该相邻节点的G和F值;
                            neighborTri.SetSessionID(pathSessionId);
                            neighborTri.SetParentID(currNode.GetID());
                            neighborTri.SetOpen(true);

                            // 计算启发值h
                            neighborTri.CalcHeuristic(endPos);
                            // 计算三角形花费g
                            neighborTri.SetGValue(currNode.GetGValue() + currNode.GetCost(neighborTri.GetID()));

                            //放入开放列表并排序
                            openList.Add(neighborTri);
                            openList.Sort(CompareTriWithGValue);

                            //保存穿入边
                            neighborTri.SetArrivalWall(currNode.GetID());
                        }
                        else
                        {
                            // 5. 如果该相邻节点在开放列表中,
                            //    则判断若经由当前节点到达该相邻节点的G值是否小于原来保存的G值,
                            //    若小于,则将该相邻节点的父节点设为当前节点,并重新设置该相邻节点的G和F值
                            if (neighborTri.GetOpen())
                            {
                                if (neighborTri.GetGValue() + neighborTri.GetCost(currNode.GetID()) < currNode.GetGValue())
                                {
                                    currNode.SetGValue(neighborTri.GetGValue() + neighborTri.GetCost(currNode.GetID()));
                                    currNode.SetParentID(neighborTri.GetID());
                                    currNode.SetArrivalWall(neighborTri.GetID());
                                }
                            }
                            else
                            {
                                neighborTri = null;
                                continue;
                            }
                        }
                    }
                }
            }

            if (closeList.Count != 0)
            {
                NavTriangle path = closeList[closeList.Count - 1];
                pathList.Add(path);
                while (path.GetParentID() != -1)
                {
                    pathList.Add(this.m_lstTriangle[path.GetParentID()]);
                    path = this.m_lstTriangle[path.GetParentID()];
                }
            }

            if (!foundPath)
            {
                return(PathResCode.NotFoundPath);
            }
            else
            {
                return(PathResCode.Success);
            }
        }
Пример #11
0
        private NavTriangle m_cTriangle;    //所在三角形

        public WayPoint(Vector2 pos, NavTriangle tri)
        {
            this.m_cPoint = pos;
            this.m_cTriangle = tri;
        }
Пример #12
0
        /// <summary>
        /// 根据原始点计算出正确的落在导航区内的位置,修复无效点和三角形
        /// </summary>
        /// <param name="orgTarTri">起源三角形</param>
        /// <param name="orgTarPos">起源点</param>
        /// <param name="otherTri">参考方向三角形</param>
        /// <param name="otherPos">参考方向点</param>
        /// <returns>结果</returns>
        private PathResCode FixPos(ref NavTriangle orgTarTri, ref Vector2 orgTarPos, NavTriangle otherTri, Vector2 otherPos, int extendLength)
        {
            Vector2 tarPos = orgTarPos;
            //////////////////////////////////////////////////////////////////////////
            //为了精确判断,需要逆向延长线段一定长度
            if (extendLength > 0)
            {
                Vector2 newTarPos = NMath.ExtendPos(otherPos, tarPos, extendLength);
                tarPos = newTarPos;
            }
            //////////////////////////////////////////////////////////////////////////

            Line2D linePath = new Line2D(tarPos, otherPos); //参考线段
            Rect lineRect = NMath.LineRect(linePath);   //获取线段矩形包围盒

            //1)找到所有与参考线段矩形相交的三角形,并判断是否groupID相等
            List<NavTriangle> crossNavTris = new List<NavTriangle>();
            foreach (NavTriangle tri in this.m_lstTriangle)
            {
                if (NMath.CheckCross(lineRect, tri.GetBoxCollider()))
                {
                    if (otherTri != null && otherTri.GetGroupID() != tri.GetGroupID())
                        continue;
                    crossNavTris.Add(tri);
                }
            }

            //2)找出所有与参考线段相交的三角形,并记录相交点
            List<Vector2> crossPoints = new List<Vector2>();    //相交点列表
            List<int> triIndex = new List<int>();   //相交三角形索引列表
            for (int index = 0; index < crossNavTris.Count; index++)
            {
                NavTriangle crossTri = crossNavTris[index];
                Line2D triLine;
                for (int i = 0; i < 3; i++)
                {
                    Vector2 insPoint;
                    triLine = new Line2D(crossTri.GetPoint(i), crossTri.GetPoint((i + 1)%3));
                    if (linePath.Intersection(triLine, out insPoint) == LineCrossState.CROSS)
                    {
                        crossPoints.Add(insPoint);
                        triIndex.Add(index);
                    }
                }
            }

            if (crossPoints.Count == 0)
                return PathResCode.NoCrossPoint;


            //3)找到最接近起源点的点
            Vector2 lastPos = crossPoints[0];
            int lastTriIndex = triIndex[0];
            double lastLength = Math.Pow(lastPos.x - orgTarPos.x, 2.0) + Math.Pow(lastPos.y - orgTarPos.y, 2.0);
            for (int i = 1; i < crossPoints.Count; i++)
            {
                double newLength = Math.Pow(crossPoints[i].x - orgTarPos.x, 2.0) + Math.Pow(crossPoints[i].y - orgTarPos.y, 2.0);
                if (newLength < lastLength)
                {
                    lastPos = crossPoints[i];
                    lastTriIndex = triIndex[i];
                    lastLength = newLength;
                }
            }

            //4)保存目标
            orgTarPos = lastPos;
            orgTarTri = crossNavTris[lastTriIndex];

            return PathResCode.Success;
        }
Пример #13
0
        /// <summary>
        /// 检查和修复所有错误路径点
        /// </summary>
        /// <param name="sTri"></param>
        /// <param name="startPos"></param>
        /// <param name="eTri"></param>
        /// <param name="endPos"></param>
        /// <returns></returns>
        private PathResCode CheckAndFixPos(ref NavTriangle startTri, ref Vector2 startPos, ref NavTriangle endTri, ref Vector2 endPos)
        {
            if ( startTri != null && endTri != null && startTri.GetGroupID() != endTri.GetGroupID())
                return PathResCode.GroupNotMatch;

            if (endTri == null)
            {
                if (FixPos(ref endTri, ref endPos, startTri, startPos, END_POS_EXTEND_LENGTH) != PathResCode.Success)
                {
                    return PathResCode.Failed;
                }
            }

            if (startTri == null)
            {
                PathResCode fixRet = FixPos(ref startTri, ref startPos, endTri, endPos, START_POS_EXTEND_LENGTH);
            }

            if (startTri == null || endTri == null)
                return PathResCode.Failed;

            if (startTri.GetGroupID() != endTri.GetGroupID())
                return PathResCode.GroupNotMatch;

            return PathResCode.Success;
        }
Пример #14
0
        /// <summary>
        /// 根据f和h实现排序,A*算法
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private int CompareTriWithGValue(NavTriangle x, NavTriangle y)
        {
            double xFvalue = x.GetHValue() /*+ x.GValue*/;
            double yFvalue = y.GetHValue() /*+ y.GValue*/;

            if (xFvalue == yFvalue)
                return 0;
            else if (xFvalue < yFvalue)
                return 1;
            else
                return -1;
        }