实现不规则图形点击区域。

新建Scene命名为IrregularShapeClick,在Scripts文件夹内新建同名文件夹。

Image组件提供的点击过滤方式(不推荐)

如果我们想让一个UI的Image组件响应不规则点击,即只有不透明部分响应点击,透明部分不响应点击,可以这样设置:

1
GetComponent<Image>().alphtHitTestMinimumThreshold = 0.1f;

alphtHitTestMinimumThreshold属性的意思是,当前UI的图片的透明部分只有大于0.1f时才会响应。

但是这种方法想要生效,就必须打开UI图片导入设置中的:Advanced——Read/Write,这会导致图片的内存使用量增大一倍。所以不推荐这种做法。

自定义不规则图形精确点击

使用自定义Image组件配合Polygon Collider 2D组件来实现精确点击。

在IrregularShapeClick文件夹内新建CustomImage脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using UnityEngine;
using UnityEngine.UI;

public class CustomImage : Image
{
private PolygonCollider2D m_Polygon;
public PolygonCollider2D Polygon
{
get
{
if (m_Polygon == null)
{
m_Polygon = GetComponent<PolygonCollider2D>();
}
return m_Polygon;
}
}
public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{
Vector3 point;
RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, screenPoint, eventCamera, out point);
return Polygon.OverlapPoint(point);
}
}

Collider2D组件提供了OverlapPoint方法,该方法能返回世界坐标内的点是否在PolygonCollider的范围内。

所以和之前的CircleImage判断点击不同的是,这里使用的是RectTransformUtility.ScreenPointToWorldPointInRectangle,返回的是世界坐标位置。

绘制PolygonCollider2D的边缘,其内部就是可点击的区域(注意整个边缘要在RectTranform框的内部,配合Button组件)。

在IrregularShapeClick文件夹内新建Editor文件夹并新建CustomImageEditor脚本,通过自定义Image组件来自动挂载Polygon Collider 2D。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;

public class CustomImageEditor
{
private const int UI_LAYER = 5;
[MenuItem("GameObject/UI/CustomImage",priority = 0)]
private static void AddImage()
{
Transform canvasTrans = GetCanvasTrans();
Transform image = AddCustomImage();

if (Selection.activeGameObject != null && Selection.activeGameObject.layer == UI_LAYER)
image.SetParent(Selection.activeGameObject.transform);
else
image.SetParent(canvasTrans);

image.localPosition = Vector3.zero;

}
private static Transform GetCanvasTrans()
{
Canvas canvas = GameObject.FindObjectOfType<Canvas>();
if (canvas == null)
{
GameObject canvasObj = new GameObject("Canvas");
SetLayer(canvasObj);
canvasObj.AddComponent<RectTransform>();
canvasObj.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
canvasObj.AddComponent<CanvasScaler>();
canvasObj.AddComponent<GraphicRaycaster>();
return canvasObj.transform;
}
else
{
return canvas.transform;
}
}
private static Transform AddCustomImage()
{
GameObject image = new GameObject("CustomImage");
SetLayer (image);
image.AddComponent<RectTransform>();
image.AddComponent<CustomImage>();
image.AddComponent<PolygonCollider2D>();
return image.transform;
}
private static void SetLayer(GameObject obj)
{
obj.layer = UI_LAYER;
}
}