赞
踩
这几天玩LOL手游,看到有个功能自定义按键位置。如下图,按键位置可以离得很近又不互相影响,划拉出来说一说常用的点击范围的问题。
屏幕上我们看到的按钮是圆形⚪,实际在开发中图片是方形 □,如下图
如果我们直接用Button做点击,那么透明区域和非透明区域都会响应点击事件
这种情况我们点击上图红框区域,有可能视觉上点击到的是A的右上,而实际触发的是B技能。
这时候就需求只让事件响应圆形区域的点击
UI.Image.IsRaycastLocationValid
这个API返回是否在点击范围,返回true则响应点击事件,false不响应
Physics2D.OverlapPoint
返回指定点是否与Collider2D重合,也就是是否在Collider2d范围内
通过以上2个API可以得出以下方式。创建CircleImage
代替Image
。调整CircleCollider2D
使碰撞区域贴合圆形区域。
public class CircleImage : Image
{
public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{
RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, screenPoint, eventCamera, out var point);
return GetComponent<CircleCollider2D>().OverlapPoint(point);
}
}
上文以圆形做示例,如果是下图的不规则图形呢
可以用PolygonCollider2D
代替以上的CircleCollider2D
附可直接使用的代码
CustomImageEditor
放在editor
文件夹
CustomImage
放正常代码文件夹
使用时可在右键UI直接创建CustomImage
,然后编辑CustomImage
的PolygonCollider2D
组件即可
using UnityEditor; using UnityEngine; using UnityEngine.UI; public class CustomImageEditor : Editor { 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("Image"); SetLayer(image); image.AddComponent<RectTransform>(); image.AddComponent<PolygonCollider2D>(); image.AddComponent<CustomImage>(); return image.transform; } private static void SetLayer(GameObject ui) { ui.layer = UI_LAYER; } }
using UnityEngine; using UnityEngine.UI; public class CustomImage : Image { private PolygonCollider2D _polygon; private PolygonCollider2D Polygon { get { if (_polygon == null) { _polygon = GetComponent<PolygonCollider2D>(); } return _polygon; } } public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) { RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, screenPoint, eventCamera, out var point); return Polygon.OverlapPoint(point); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。