Мне нужно проверить, пересекаются ли две линии.Они в настоящее время обернуты в краевые коллайдеры.
В моем минимальном примере я использую Collider2D.OverlapsCollider
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);
}
}
}
Вот как я настроил свою сцену:
Как видно на рисунке выше, две линии четко пересекаются.
Проблема в том, что на консоль ничего не выводится.
Я не уверен на 100% о том, как ContactFilter
должен быть настроен, но, глядя на документацию, он используется для фильтрации результатов.Таким образом, оставляя это поле пустым, нужно включить все.
Мне действительно нужно сделать проверку между двумя строками.Поэтому функция, которая принимает их в качестве аргументов и возвращает логическое значение, указывающее на пересечение, была бы наиболее удобной.К сожалению, я не смог найти такую функцию в Unity.
Не следует слишком усложнять создание этой функции самостоятельно, но я бы предпочел использовать функции, обеспечивающие единство, в максимально возможной степени.Поэтому рассмотрим это скорее как вопрос, связанный с единством, чем вопрос, связанный с математикой.
РЕДАКТИРОВАТЬ:
Использование Collider2D.IsTouching(Collider2D)
, похоже, тоже не работает.Вместо этого я использую ту же настройку, что и раньше, с этим кодом:
public class EdgeColliderChecker : MonoBehaviour
{
public EdgeCollider2D e1;
public EdgeCollider2D e2;
void Update () {
if (e1.IsTouching(e2)) {
Debug.Log("INTERSECTION");
}
}
}
Редактировать 2:
Я попытался создать свой собственный метод для этого:
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
:
public class EdgeColliderChecker : MonoBehaviour
{
public EdgeCollider2D e1;
void Update ()
{
List<Collider2D> hits = e1.GetInterSections();
if (hits.Count > 0) {
Debug.Log(hits.Count);
}
}
}
Все равно ничего.Несмотря на то, что точки, которые я вычисляю, идеально совпадают с коллайдером:
Я сделал это для математики, и, похоже, он работает хорошо, не очень проверено,Проверка пересечения немного прерывистая, если она запускается во время движения коллайдеров:
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;
}
}
Но я бы очень хотел использовать вместо этого что-то, предоставленное единицей.