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
相关产品推荐
相关产品推荐

