首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检查两条线是否相交

检查两条线是否相交
EN

Stack Overflow用户
提问于 2018-10-11 02:25:34
回答 3查看 1.4K关注 0票数 0

我要检查两条线是否相交。这些当前被包裹在边缘对撞器中。

在我的最小示例中,我使用了Collider2D.OverlapsCollider

代码语言:javascript
复制
public class EdgeColliderChecker : MonoBehaviour
{
    public EdgeCollider2D e1;
    public EdgeCollider2D e2;

    void Update () {
        Collider2D[] results1 = new Collider2D[1];
        e1.OverlapCollider(new ContactFilter2D(), results1);
        if (results1[0] != null)
        {
            Debug.Log(results1[0].name);
        }

        Collider2D[] results2 = new Collider2D[1];
        e1.OverlapCollider(new ContactFilter2D(), results2);
        if (results2[0] != null) {
            Debug.Log(results2[0].name);
        }
    }
}

这是我设置场景的方式:

正如你在上面的图片中看到的,这两条线显然是相交的。

问题是没有任何东西输出到控制台。

我不是百分之百确定ContactFilter应该如何配置,但看看文档,它是用来过滤结果的。因此,将其保留为空应该包括所有内容。

我真的只需要在两行之间进行检查。因此,将它们作为参数并返回指示交集的布尔值的函数将是最方便的。不幸的是,我在Unity中找不到这样的函数。

我自己构造函数应该不会太复杂,但我更喜欢使用unity提供的函数。因此,与其说这是一个与数学有关的问题,不如说是一个与统一性有关的问题。

编辑:

使用Collider2D.IsTouching(Collider2D)似乎也不起作用。我使用与前面相同的设置来代替下面的代码:

代码语言:javascript
复制
public class EdgeColliderChecker : MonoBehaviour
{
    public EdgeCollider2D e1;
    public EdgeCollider2D e2;

    void Update () {
        if (e1.IsTouching(e2)) {
            Debug.Log("INTERSECTION");
        }
    }
}

编辑2:

为此,我尝试创建自己的方法:

代码语言:javascript
复制
public static class EdgeColliderExtentions {
    public static List<Collider2D> GetInterSections(this EdgeCollider2D collider)
    {
        List<Collider2D> intersections = new List<Collider2D>();
        Vector2[] points = collider.points;
        for (int i = 0; i < points.Length - 1; i++)
        {
            Vector2 curr = collider.transform.TransformPoint(points[i]);
            Vector2 next = collider.transform.TransformPoint(points[i + 1]);
            Vector2 diff = next - curr;

            Vector2 dir = diff.normalized;

            float distance = diff.magnitude;

            RaycastHit2D[] results = new RaycastHit2D[30];
            ContactFilter2D filter = new ContactFilter2D();

            Debug.DrawLine(curr, curr + dir * distance, Color.red, 1 / 60f);

            int hits = Physics2D.Raycast(curr, dir, filter, results, distance);

            for (int j = 0; i < hits; i++)
            {
                Collider2D intersection = results[j].collider;
                if (intersection != collider)
                {
                    intersections.Add(intersection);
                }
            }
        }
        return intersections;
    }
}

EdgeColliderChecker

代码语言:javascript
复制
public class EdgeColliderChecker : MonoBehaviour
{
    public EdgeCollider2D e1;

    void Update ()
    {
        List<Collider2D> hits = e1.GetInterSections();
        if (hits.Count > 0) {
            Debug.Log(hits.Count);
        }
    }
}

还是一无所获。即使我计算的点与对撞机完全一致:

我为它做了数学计算,它似乎工作得很好,但测试不是很彻底。如果交叉点检查是在碰撞机四处移动时运行的,则交叉点检查会有一点起伏:

代码语言:javascript
复制
public class Line {
    private Vector2 start;
    private Vector2 end;

    public Line(Vector2 start, Vector2 end)
    {
        this.start = start;
        this.end = end;
    }

    public static Vector2 GetIntersectionPoint(Line a, Line b)
    {
        //y = kx + m;
        //k = (y2 - y1) / (x2 - x1)
        float kA = (a.end.y - a.start.y) / (a.end.x - a.start.x);
        float kB = (b.end.y - b.start.y) / (b.end.x - b.start.x);

        //m = y - k * x
        float mA = a.start.y - kA * a.start.x;
        float mB = b.start.y - kB * b.start.x;

        float x = (mB - mA) / (kA - kB);
        float y = kA * x + mA;
        return new Vector2(x,y);
    }

    public static bool Intersects(Line a, Line b)
    {
        Vector2 intersect = GetIntersectionPoint(a, b);            

        if (Vector2.Distance(a.start, intersect) < Vector2.Distance(a.start, a.end) &&
            Vector2.Distance(a.end, intersect) < Vector2.Distance(a.start, a.end))
        {
            return true;
        }
        return false;
    }
}

public static class EdgeColliderExtentions
{
    public static bool Intersects(this EdgeCollider2D collider, EdgeCollider2D other)
    {
        Vector2[] points = collider.points;
        Vector2[] otherPoints = other.points;
        for (int i = 0; i < points.Length - 1; i++)
        {
            Vector2 start = collider.transform.TransformPoint(points[i]);
            Vector2 end = collider.transform.TransformPoint(points[i + 1]);
            Line line = new Line(start, end);
            for (int j = 0; j < otherPoints.Length - 1; j++)
            {
                Vector2 otherStart = other.transform.TransformPoint(otherPoints[i]);
                Vector2 otherEnd = other.transform.TransformPoint(otherPoints[i + 1]);
                Line otherLine = new Line(otherStart, otherEnd);
                if (Line.Intersects(line, otherLine))
                {
                    return true;
                }
            }
        }
        return false;
    }
}

但是我真的很想用unity提供的东西来代替。

EN

回答 3

Stack Overflow用户

发布于 2018-10-11 02:41:28

使用Collider.bounds.Intersects(Collider.bounds)确定两个边界是否相交:

代码语言:javascript
复制
void Update () {
    if (e1.bounds.Intersects(e2.bounds)) {
        Debug.Log("Bounds intersecting");
    }
}

不幸的是,这不会让你知道边缘是否相交。但是,如果测试结果为假,则可以跳过边缘测试。

票数 1
EN

Stack Overflow用户

发布于 2018-10-12 06:52:05

我意识到我可以根据我的用例将其中一个边缘对撞器交换为多边形对撞器。

Collider2D.OverlapsCollider()中使用多边形和边碰撞器可以按预期工作。

我不知道我是否应该接受这个答案,因为它没有解决最初的问题,即在单位中寻找直线相交的函数。

票数 1
EN

Stack Overflow用户

发布于 2018-10-12 14:01:36

您可以使用以下内容获得相对接近的近似结果:

你可以创建一个脚本,沿着这条线均匀地添加几个小盒子碰撞器,越多越好。然后进行正常的碰撞检测。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52746588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档