【问题标题】:Detect if a vector2 is between two other vector2检测一个vector2是否在另外两个vector2之间
【发布时间】:2019-12-23 17:18:40
【问题描述】:

正如标题所示,我正在尝试不同的方法,但没有解决。 我需要检查鼠标是否在 PlayMode 中的两个 2d 点之间。 我想过使用 rect 在两个 vector2 之间动态构建一个矩形,并使用 rect.contains 检查鼠标位置是否在矩形内。如果矩形是水平的但屏幕上的点未对齐,并且在我看来没有办法创建倾斜矩形,则此方法有效。 我试图计算两点之间的 距离,创建矩形并移动其 center 以旋转它,但它似乎不起作用。此外,似乎没有办法在屏幕上显示矩形,因此很难理解在更改某些参数后它是否保持原来的形状。 你有什么建议吗?但我需要检测区域是矩形的,而不是在一条线上。使用LineCast可以解决,但是检测到的区域太窄。

我想到了两个向量之间的一个矩形。想象一条连接两个向量的单像素线。现在将线条的粗细增加到 10/20 像素,以便在原始线条之前和之后检测到鼠标。也许我错了,但我认为新的 rect 是一个很好的解决方案,但就我查看它的所有属性而言,我无法理解如何在没有太多代码行的情况下在两个向量之间构建它。

【问题讨论】:

  • 屏幕上的点不对齐是什么意思?始终可以在 2 个 2D 点之间构建一个矩形。如果“未对齐”意味着一个比另一个更深,只需移除深度分量即可。
  • “两点”是指两个 Vector2。例如 Vector2 (10,10) 和 Vector2 (50,50)。我需要检测鼠标何时在连接两个向量的线上。但是单条线很窄,很难通过将鼠标悬停在上面来检测。出于这个原因,我想到了一个矩形。当我说这些点未对齐时,我的意思是它们不在同一个 y 轴上,z 轴为 0。我确定我错了,但是如何构建一个从一个向量 2 倾斜到另一个向量 2 的新矩形?
  • 找到从鼠标位置到你的两点定义的线的距离。如果该距离低于某个阈值,则认为它“在线”。
  • 目的是将这个系统用作对撞机。出于这个原因,我想到了两个向量之间的矩形。想象一条连接两个向量的单像素线。现在将线条的粗细增加到 10/20 像素,以便在原始线条之前和之后检测到鼠标。也许我错了,但我认为新的 rect 是一个很好的解决方案,但就我查看它的所有属性而言,我无法理解如何在没有太多代码行的情况下在两个向量之间构建它。

标签: c# unity3d


【解决方案1】:

你可以做一些向量数学来:

  1. 确定测试点是否不在两个点的“外部”。

  2. 计算您的点与线段的距离,如果等于或低于某个阈值,则认为它“靠近”两点之间的线段。

  3. 如果它“靠近”该段而不是“外部”两点,则认为它位于两点“之间”。

例如:

Vector3 point1 = new Vector2(10f, 10f);
Vector3 point2 = new Vector2(50f, 50f);
float closeThreshold = 5f;

Vector3 testPoint = new Vector2(20f, 21f);

Vector3 segmentDirection = (point2-point1).normalized;
Vector3 point1ToTest = testPoint - point1;
Vector3 testToPoint2 = point2 - testPoint;

// determine if testPoint is not "outside" the points
if (       Vector3.Dot(segmentDirection, point1ToTest.normalized) >= 0f
        && Vector3.Dot(segmentDirection, testToPoint2.normalized) >= 0f)
{
    Vector3 closestPointOnSegment = point1 
            + segmentDirection * Vector3.Dot(point1ToTest, segmentDirection);

    // determine if testPoint is close enough to the line segment point1->point2
    if ((closestPointOnSegment - testPoint).magnitude <= closeThreshold)
    {
        // testPoint is "between" point1 and point2
    } 
}

这将与Vector3Vector2 一起使用,它们将安全地转换为Vector3,如上所示。


如果您只关心该点是否正好在两个位置之间,请从您要测试的点到线的任一端获取方向,如果这些方向之间的点积为 -1,则点在他们之间:

Vector3 point1 = new Vector2(-1f,-1f);
Vector3 point2 = new Vector2(1f,1f);

Vector3 testPoint = new Vector2(0f,0f);

Vector3 testTo1 = (point1-testPoint).normalized;
Vector3 testTo2 = (point2-testPoint).normalized;

if (Mathf.Approximately(-1f, Vector3.Dot(testTo1, testTo2)))
{
    // testPoint is between point1 and point2
}

这将适用于Vector3Vector2,它们将安全地转换为Vector3,如上所述。

【讨论】:

  • 很好,但testPoint 必须几乎完全在线才能工作。我会添加一个软糖因素,例如检查.Dot 结果是否在-0.9-1 之间。 (由于 OP 使用鼠标位置作为测试点,我想这是用于选择/拾取。)
  • 是的,你是对的,我们的目标是使用这个系统作为对撞机。出于这个原因,我想到了两个向量之间的一个矩形。
  • @3Dave 啊,我在提问者澄清之前写了这个。像这样使用Dot 使得它在不同点之间的数量不同。我选择了不同的解决方案。请查看更新。
  • ...但是现在我正在考虑它,当鼠标靠近段端点时可能会出现一些问题。所以,新版本可能是一个更好的答案。我没有足够的动力去测试它。 :)
  • @3Dave 是的,这就是想法 - 像这样比较 Dot 使得它在点之间的中间比在末端更宽松。新答案是您在问题的 cmets 中建议的实现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多