Ejemplo n.º 1
0
 /// <summary>
 /// 射线检测可走性。
 /// 返回True表示检测到障碍
 /// </summary>
 public bool LineCastForMoving(ref HitInfo hit, MoveType mov)
 {
     return(navgationGraph.LineCastForMoving(ref hit, mov));
 }
Ejemplo n.º 2
0
        public override bool LineCastForMoving(ref HitInfo hit, MoveType mov)
        {
            Int3 from = hit.from;
            Int3 to   = hit.to;

            hit.hitPosition = from;

            if (trace != null)
            {
                trace.Clear();
            }

            Int3 end    = to;
            Int3 origin = from;

            if (origin == end)
            {
                hit.hitPosition = from;
                return(false);
            }

            NavMeshNode node = GetNearest(from, NNConstraint.None).node;

            if (node == null)
            {
                Debug.LogError("Could not find a valid node to start from");
                hit.hitPosition = from;
                return(true);
            }

            origin = node.ClosestPointOnNode(origin);

            List <Int3> left = Util.ListPool <Int3> .Claim();

            List <Int3> right = Util.ListPool <Int3> .Claim();

            int counter = 0;

            while (true)
            {
                counter++;
                if (counter > 2000)
                {
                    Debug.LogError("Linecast was stuck in infinite loop. Breaking.");
                    Util.ListPool <Int3> .Release(left);

                    Util.ListPool <Int3> .Release(right);

                    return(true);
                }

                NavMeshNode newNode = null;

                if (trace != null)
                {
                    trace.Add(node);
                }

                if (node.ContainsPoint(end))
                {
                    hit.hitPosition = to;
                    Util.ListPool <Int3> .Release(left);

                    Util.ListPool <Int3> .Release(right);

                    return(false);
                }

                for (int i = 0; i < node.connections.Length; i++)
                {
                    left.Clear();
                    right.Clear();

                    NavMeshNode other = GetNode(node.connections[i]) as NavMeshNode;
                    if (!node.GetPortal(other, left, right))
                    {
                        continue;
                    }

                    Int3 a = left[0];
                    Int3 b = right[0];

                    //i.e Left or colinear
                    if (!VectorMath.RightXZ(a, b, origin))
                    {
                        if (VectorMath.RightXZ(a, b, end))
                        {
                            //Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it
                            continue;
                        }
                    }

                    float factor1, factor2;

                    if (VectorMath.LineIntersectionFactorXZ(a, b, origin, end, out factor1, out factor2))
                    {
                        //Intersection behind the start
                        if (factor2 < 0)
                        {
                            continue;
                        }

                        if (factor1 >= 0 && factor1 <= 1)
                        {
                            newNode = other;
                            break;
                        }
                    }
                }

                if (newNode == null)
                {
                    //Possible edge hit
                    int vs = node.GetVertexCount();

                    for (int i = 0; i < vs; i++)
                    {
                        var a = node.GetVertex(i);
                        var b = node.GetVertex((i + 1) % vs);


                        //i.e left or colinear
                        if (!VectorMath.RightXZ(a, b, origin))
                        {
                            //Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it
                            if (VectorMath.RightXZ(a, b, end))
                            {
                                //Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it
                                continue;
                            }
                        }

                        float factor1, factor2;
                        if (VectorMath.LineIntersectionFactorXZ(a, b, origin, end, out factor1, out factor2))
                        {
                            if (factor2 < 0)
                            {
                                continue;
                            }

                            if (factor1 >= 0 && factor1 <= 1)
                            {
                                Vector3 intersectionPoint = (Vector3)a + (Vector3)(b - a) * factor1;
                                hit.hitPosition = new Int3(intersectionPoint);

                                Util.ListPool <Int3> .Release(left);

                                Util.ListPool <Int3> .Release(right);

                                return(true);
                            }
                        }
                    }

                    //Ok, this is wrong...
                    Debug.LogWarning("Linecast failing because point not inside node, and line does not hit any edges of it");

                    Util.ListPool <Int3> .Release(left);

                    Util.ListPool <Int3> .Release(right);

                    return(false);
                }

                node = newNode;
            }
        }
Ejemplo n.º 3
0
        // 射线碰撞,计算起点到终点间的最远可到达点
        public override bool LineCastForMoving(ref HitInfo hit, MoveType mov)
        {
            Int3 from = hit.from;
            Int3 to   = hit.to;

            Int3 blockPoint = from;
            int  stepLen    = Math.Min(200, navData.GridSize);
            bool blocked    = false;

            // y = a*x + b
            Fix64 a  = (Fix64)0;
            int   dx = to.x - from.x;
            int   dz = to.z - from.z;

            if (Math.Abs(dx) > Math.Abs(dz))
            {
                a = (Fix64)dz / (Fix64)dx;
                int step = to.x - from.x > 0 ? stepLen : -stepLen;
                for (int x = from.x + step; step > 0 ? x <to.x + step : x> to.x - step; x += step)
                {
                    x = step > 0 ? Math.Min(x, to.x) : Math.Max(x, to.x);
                    Fix64 z      = (Fix64)from.z + a * (Fix64)(x - from.x);
                    var   tmpPos = new Int3(x, 0, (int)z);
                    if (!IsWalkable(tmpPos))
                    {
                        if (!SpecialTerrainPassable(tmpPos, mov))
                        {
                            blocked = true;
                            break;
                        }
                    }

                    blockPoint.Set(x, from.y, (int)z);
                }
            }
            else
            {
                a = (Fix64)dx / (Fix64)dz;
                int step = to.z - from.z > 0 ? stepLen : -stepLen;
                for (int z = from.z + step; step > 0 ? z <to.z + step : z> to.z - step; z += step)
                {
                    z = step > 0 ? Math.Min(z, to.z) : Math.Max(z, to.z);
                    Fix64 x      = (Fix64)from.x + a * (Fix64)(z - from.z);
                    var   tmpPos = new Int3((int)x, 0, z);
                    if (!IsWalkable(tmpPos))
                    {
                        if (!SpecialTerrainPassable(tmpPos, mov))
                        {
                            blocked = true;
                            break;
                        }
                    }

                    blockPoint.Set((int)x, from.y, z);
                }
            }

            if (blockPoint != from)
            {
                hit.hitPosition = blockPoint;
            }
            else
            {
                hit.hitPosition = to;
            }
            return(blocked);
        }