You need to enable JavaScript to run this app. 如何在LineRenderer的两Vector2端点间取点,缩短线段避免共端点误判相交
优惠活动
大模型
产品
解决方案
定价
更多

如何在LineRenderer的两Vector2端点间取点,缩短线段避免共端点误判相交

如何在LineRenderer两点线段上取指定中间点,解决端点接触误判相交的问题

线段取点示例

问题背景

  • 当前使用LineRenderer绘制仅包含起点、终点两个Vector2坐标的线段,需要获取图中标记的中间点A
  • 核心诉求是对原线段做长度缩短,修正现有二维相交检测的误判逻辑:当前检测下,两条线段只要从同一点出发(纯端点接触)就会被判定为相交,希望通过相交前的线段缩短处理,让仅端点重合的场景不被误判。
  • 现有检测逻辑为基于点积的二维线段相交判断,代码如下:
public bool isIntersecting = false;
LineRenderer lineRenderer;

private void Start()
{
    lineRenderer = this.GetComponent<LineRenderer>();
}

private void Update()
{
    LineRenderer recievedLine;
    if (FindObjectOfType<LineDynamics>().ropeRenderer != null)
    {
        recievedLine = FindObjectOfType<LineDynamics>().ropeRenderer;
    }
    else
    {
        return;
    }

    // 传入线段端点执行相交检测
    AreLineSegmentsIntersectingDotProduct(lineRenderer.GetPosition(0), lineRenderer.GetPosition(lineRenderer.positionCount - 1), recievedLine.GetPosition(0), recievedLine.GetPosition(recievedLine.positionCount - 1));
}

// 基于点积的二维线段相交检测
// p1、p2为第一条线段端点,p3、p4为第二条线段端点
public bool AreLineSegmentsIntersectingDotProduct(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
{
    if (IsPointsOnDifferentSides(p1, p2, p3, p4) && IsPointsOnDifferentSides(p3, p4, p1, p2))
    {
        isIntersecting = true;
    }
    else
    {
        isIntersecting = false;
    }

    return isIntersecting;
}

// 判断两点是否位于目标线段两侧
private bool IsPointsOnDifferentSides(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4)
{
    bool isOnDifferentSides = false;
    // 目标线段方向向量
    Vector2 lineDir = p2 - p1;
    // 线段法向量
    Vector2 lineNormal = new Vector2(-lineDir.y, lineDir.x);
    // 计算两个跨线点相对于线段的点积
    float dot1 = Vector2.Dot(lineNormal, p3 - p1);
    float dot2 = Vector2.Dot(lineNormal, p4 - p1);
    // 点积乘积为负,说明两点在线段两侧
    if (dot1 * dot2 < 0f)
    {
        isOnDifferentSides = true;
    }

    return isOnDifferentSides;
}

解决方法

1. 线段上中间点的计算

两个Vector2端点构成的线段,不需要依赖LineRenderer组件,直接通过向量运算即可获取任意位置的中间点:

  • 先计算从起点指向终点的方向向量,除以自身模长得到单位方向向量,代表沿线段每移动1个单位长度的坐标增量
  • 沿方向向量偏移指定长度,即可得到目标中间点坐标
    直接使用以下工具方法获取两端等长缩短后的线段端点:
/// <summary>
/// 对原线段做两端等长缩短,返回缩短后的新端点
/// </summary>
/// <param name="originalStart">原线段起点</param>
/// <param name="originalEnd">原线段终点</param>
/// <param name="shortenOffset">两端各自缩短的固定长度</param>
/// <returns>缩短后的新起点、新终点</returns>
public (Vector2 newStart, Vector2 newEnd) GetShortenedLine(Vector2 originalStart, Vector2 originalEnd, float shortenOffset)
{
    Vector2 lineDir = originalEnd - originalStart;
    float lineLength = lineDir.magnitude;
    // 线段过短时直接返回原端点,避免除零异常
    if (lineLength <= shortenOffset * 2)
    {
        return (originalStart, originalEnd);
    }
    Vector2 unitDir = lineDir / lineLength;
    Vector2 newStart = originalStart + unitDir * shortenOffset;
    Vector2 newEnd = originalEnd - unitDir * shortenOffset;
    return (newStart, newEnd);
}

如果需要按长度比例取点(比如从起点走总长度30%的位置),可以直接使用Unity内置的Vector2.Lerp(originalStart, originalEnd, t)方法,t为0到1之间的插值系数。

2. 相交检测误判修正

  • 调用相交检测逻辑前,分别对两条待检测线段执行上述缩短操作,根据项目的坐标尺度选择合适的缩短阈值(通常取0.001~0.05个世界单位)
  • 用缩短后的线段端点传入现有相交检测方法,此时如果两条原线段是纯端点重合的场景,缩短后的端点会向线段内部偏移固定距离,不会和另一条缩短后的线段产生接触,自然不会被误判为相交
  • 调整时注意缩短阈值不能过大,否则会漏掉距离端点过近的真实相交场景,可根据项目实际精度需求微调

检测逻辑精度优化

原IsPointsOnDifferentSides方法可以增加浮点容错阈值,避免坐标计算的微小误差导致误判:
将原有的严格小于0的判断,改为点积乘积小于固定负值阈值时才判定为两点在两侧:

// 替换原有判断逻辑
if (dot1 * dot2 < -0.00001f)
{
    isOnDifferentSides = true;
}

内容的提问来源于stack exchange,提问作者Bhavin Lathia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.01 15:36:07