You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何检测2D Sprite的所有边缘点是否被触摸?

实现Polygon Collider 2D边缘点触摸检测与画线提示

核心逻辑拆解

需要完成两个核心功能:追踪所有边缘点的触摸完成状态,以及实时绘制触摸碰撞位置的提示线条。以下是针对Unity新手的分步实现方案:

步骤实现

1. 提取Polygon Collider的边缘点数据

首先要将Collider的本地顶点转换为世界坐标,方便后续触摸检测:

private List<Vector2> _edgePoints = new List<Vector2>();
private HashSet<int> _touchedPointIndices = new HashSet<int>();

void Start()
{
    PolygonCollider2D polygonCollider = GetComponent<PolygonCollider2D>();
    // 遍历所有子路径(处理多形状/带孔洞的Collider)
    for (int pathIndex = 0; pathIndex < polygonCollider.pathCount; pathIndex++)
    {
        Vector2[] localPathPoints = polygonCollider.GetPath(pathIndex);
        foreach (Vector2 localPoint in localPathPoints)
        {
            // 转换为世界坐标并存入列表
            _edgePoints.Add(polygonCollider.transform.TransformPoint(localPoint));
        }
    }
}

2. 触摸检测与边缘点追踪

在Update中处理触摸输入,通过碰撞检测确定触摸位置是否在Collider内,再匹配最近的边缘点:

public float touchThreshold = 0.15f; // 触摸判定的距离阈值,可根据画面调整
public int completionScore = 10;

void Update()
{
    if (Input.touchCount == 0) return;

    Touch currentTouch = Input.GetTouch(0);
    Vector2 touchWorldPos = Camera.main.ScreenToWorldPoint(currentTouch.position);
    touchWorldPos.z = 0; // 2D场景强制z轴一致

    // 检测触摸点是否命中目标Collider
    Collider2D hitCollider = Physics2D.OverlapPoint(touchWorldPos);
    if (hitCollider != null && hitCollider == GetComponent<PolygonCollider2D>())
    {
        // 找到距离触摸点最近的边缘点
        int closestPointIndex = GetClosestEdgePointIndex(touchWorldPos);
        if (closestPointIndex == -1) return;

        // 距离小于阈值则标记该点已触摸
        if (Vector2.Distance(touchWorldPos, _edgePoints[closestPointIndex]) < touchThreshold)
        {
            _touchedPointIndices.Add(closestPointIndex);
        }

        // 更新提示线条
        UpdateHintLine(touchWorldPos, closestPointIndex);
    }

    // 检查所有边缘点是否都已触摸完成
    if (_touchedPointIndices.Count == _edgePoints.Count)
    {
        AddScore();
        _touchedPointIndices.Clear(); // 重置状态,避免重复加分
    }
}

// 获取最近的边缘点索引
private int GetClosestEdgePointIndex(Vector2 targetPos)
{
    int index = -1;
    float minDistance = float.MaxValue;
    for (int i = 0; i < _edgePoints.Count; i++)
    {
        float distance = Vector2.Distance(targetPos, _edgePoints[i]);
        if (distance < minDistance)
        {
            minDistance = distance;
            index = i;
        }
    }
    return index;
}

private void AddScore()
{
    // 替换为你的分数逻辑,比如调用全局分数管理类
    Debug.Log($"完成触摸!分数+{completionScore}");
}

3. Line Renderer绘制触摸提示

先给目标物体添加Line Renderer组件,设置好材质和线条宽度,再通过代码实时更新线条位置:

private LineRenderer _lineRenderer;

void Awake()
{
    _lineRenderer = GetComponent<LineRenderer>();
    _lineRenderer.positionCount = 2;
    _lineRenderer.startWidth = 0.06f;
    _lineRenderer.endWidth = 0.06f;
    _lineRenderer.useWorldSpace = true; // 必须勾选,使用世界坐标绘制
}

private void UpdateHintLine(Vector2 touchPos, int closestPointIndex)
{
    // 线条从触摸点指向最近的未触摸边缘点
    _lineRenderer.SetPosition(0, touchPos);
    _lineRenderer.SetPosition(1, _edgePoints[closestPointIndex]);
}

针对Willow方案的常见问题调整

如果你尝试Willow的方案后遇到异常,优先检查这几点:

  • 确保Polygon Collider 2D的Is Trigger未勾选(Physics2D.OverlapPoint仅对非Trigger Collider生效)
  • 触摸阈值不要设置过小,否则会导致难以触发点标记;过大则可能误触多个点
  • Line Renderer的Use World Space必须勾选,否则线条会以局部坐标绘制,出现错位
  • 边缘点转换时必须用TransformPoint转世界坐标,不要直接使用本地顶点数据

内容的提问来源于stack exchange,提问作者Roshan Chapagain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 09:54:59