实现不规则图形点击区域。
新建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; } }
|