需求:圆形外观按钮,圆形区域外不希望被响应。
问题:unity image 响应区域为方形范围,无法支持圆形点击限制。
处理方案:自定义 CircleEventImage 继承自 Image 复写IsRaycastLocationValid 函数,计算点击点是否处于圆形区域内。
初始方案:CircleCollider2D 检测点击点是否再 圆形区域。代码如下:
public class CircleEventImage : Image
{
CircleCollider2D m_pCollider;
RectTransform m_pRTran;
protected override void Start()
{
base.Start();
m_pRTran = GetComponent<RectTransform>();
m_pCollider = gameObject.GetComponent<CircleCollider2D>();
}
public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{
bool bRayUI = base.IsRaycastLocationValid(screenPoint, eventCamera);
if (bRayUI && m_pCollider != null)
{
bRayUI = m_pCollider.OverlapPoint(screenPoint);
}
return bRayUI;
}
}
遇到新问题:由于Transform 位置,对其方是不对导致 OverlapPoint 判断结果不准确。
添加位置转换逻辑,复写的IsRaycastLocationValid方法代码如下:
public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{
bool bRayUI = base.IsRaycastLocationValid(screenPoint, eventCamera);
if (bRayUI && m_pCollider != null)
{
Vector3 localPos;
//RectTransformUtility.ScreenPointToLocalPointInRectangle(m_pRTran, screenPoint, eventCamera, out localPos);
RectTransformUtility.ScreenPointToWorldPointInRectangle(m_pRTran, screenPoint, eventCamera, out localPos);
//Debug.Log("Screen point:" + screenPoint + " bound:" + m_pCollider.bounds);
bRayUI = m_pCollider.OverlapPoint(localPos);
}
return bRayUI;
}
功能上基本能完成需求,但是又遇到新的问题 该子类无法想image类一样在Inspector面板设置如下内容可以通过如下方式指定自定义面板显示。这里我们使用ImageEditor.
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UI;
[CustomEditor(typeof(ImageEditor))]
#endif
public class CircleEventImage : Image
{
注意需要将
using UnityEditor;
using UnityEditor.UI
限定在 UNITY_EDITOR 模式下,否则打包可能会出错。
同时,如果使用了自定义的Editor 需要将文件目录放置到 Editor 文件夹或其子文件夹下。