您的位置:首页 > 移动开发 > Unity3D

Unity 指引遮罩

2016-03-18 14:45 459 查看
指引遮罩层的作用,主要是屏蔽事件,指定区域穿透事件。在视觉上,遮挡是非遮挡区域有不同的颜色表示。我们分别从事件功能,和视觉功能上来分别介绍。事件功能需要脚本,视觉功能需要shader辅助。本文主要介绍事件功能的实现,shader的视觉辅助下篇介绍。

事件功能上,我们建立四个遮挡层,每个层都会阻挡事件。让后利用4块遮挡层,去围成一个矩形区域形成可点击区域。我们生成一个prefab,里面包含4个屏蔽层。动态的去计算4个屏蔽层的位置。

public RectTransform   top;
public RectTransform   bottom;
public RectTransform   left;
public RectTransform   right;

private void SetRectCenterInner(Vector2 center, Vector2 size)
{  
RectTransform   root     = uiRoot.GetComponent<RectTransform>();
Vector2         half     = root.sizeDelta * root.localScale.x / 2;
Vector2         halfSize = size           * root.localScale.x / 2;

top.sizeDelta            = root.sizeDelta;
bottom.sizeDelta         = root.sizeDelta;
left.sizeDelta           = root.sizeDelta;
right.sizeDelta          = root.sizeDelta;

Vector2 tl               = new Vector2(center.x - halfSize.x, center.y + halfSize.y);
Vector2 br               = new Vector2(center.x + halfSize.x, center.y - halfSize.y);

top.position             = new Vector3(0, tl.y + half.y, 0);
bottom.position          = new Vector3(0, br.y - half.y, 0);

left.position            = new Vector3(tl.x - half.x, br.y + halfSize.y, 0);
right.position           = new Vector3(br.x + half.x, br.y + halfSize.y, 0);

left.sizeDelta           = new Vector2(left.sizeDelta.x,  size.y);
right.sizeDelta          = new Vector2(right.sizeDelta.x, size.y);
}


这里代码片段,是根据可点击区域的中心点和大小,动态计算4个屏蔽区域位置和大小的功能。这里做了适配屏幕的缩放计算。那么,可点击区域,如何让事件接受处理,又能够穿透下去,让本来的事件可以触发执行呢。

我们需要建立另外一个层,覆盖在可点击区域上。实现ICanvasRaycastFilter接口,return false 将会被系统认为碰撞检测失败,事件会被继续传递,同时我们可以再接口中实现我们自己需要的回调。

public class EventIgnore : MonoBehaviour, ICanvasRaycastFilter
{
public Action action;

public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
if (Input.GetMouseButtonDown(0))
{
action();
}

#else
if (Input.touchCount == 1)
{
Touch touch = Input.GetTouch(0);

if (touch.phase == TouchPhase.Began)
{
action();
}
}
#endif
return false;
}


脚本需要和Image挂载在一起,通过Image的区域来触发碰撞检测。Action的回调中,我们可以把屏蔽层关闭。这个区域需要和上面屏蔽层围成的区域重叠起来。

public class GuideMask : MonoBehaviour
{
public RectTransform   top;
public RectTransform   bottom;
public RectTransform   left;
public RectTransform   right;
public RectTransform   eventArea;

private void SetRectCenterInner(Vector2 center, Vector2 size)
{
RectTransform   root     = uiRoot.GetComponent<RectTransform>();
Vector2         half     = root.sizeDelta * root.localScale.x / 2;
Vector2         halfSize = size           * root.localScale.x / 2;

top.sizeDelta            = root.sizeDelta;
bottom.sizeDelta         = root.sizeDelta;
left.sizeDelta           = root.sizeDelta;
right.sizeDelta          = root.sizeDelta;

Vector2 tl               = new Vector2(center.x - halfSize.x, center.y + halfSize.y);
Vector2 br               = new Vector2(center.x + halfSize.x, center.y - halfSize.y);

top.position             = new Vector3(0, tl.y + half.y, 0);
bottom.position          = new Vector3(0, br.y - half.y, 0);

left.position            = new Vector3(tl.x - half.x, br.y + halfSize.y, 0);
right.position           = new Vector3(br.x + half.x, br.y + halfSize.y, 0);

left.sizeDelta           = new Vector2(left.sizeDelta.x,  size.y);
right.sizeDelta          = new Vector2(right.sizeDelta.x, size.y);

eventArea.position       = new Vector3(center.x, center.y, 0);
eventArea.sizeDelta      = size;
}
}


eventArea 是可点击事件层,EventIgnore 挂载层上,完成事件的穿透和响应双重工作。上面代码仅体现思路,是完成功能代码中截取的,并非直接可以运行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: