Unity实现新手引导镂空效果

本文实例为大家分享了Unity实现新手引导镂空效果的具体代码,供大家参考,具体内容如下

一、实现思路

创建有8个顶点的Mesh,内外边界都是四边形(矩形)。只生成内、外边之间的Mesh,内层矩形就产生了镂空部分,外层的4个顶点,是组件自身RectTransform的四个顶点,内层的4个顶点,使用镂空目标(_target)RectTransform的四个顶点。确定内层的顶点的时候需要注意,多数情况下_target和HollowOutMask都不在同一个本地坐标空间,所以需要使用CalculateRelativeRectTransformBounds计算出HollowOutMask空间下坐标

这种镂空的表现,可以稍稍提高下性能。因为镂空的位置不参与渲染,Overdraw会降低

UGUI提供了ICanvasRaycastFilter接口,我们实现IsRaycastLocationValid方法,就可以很方便的控制HollowOutMask是否要拦截下在某一点触发的事件

二、这个组件的作用

这个组件做了两件事情:表现上镂空一块区域和不拦截镂空范围上的事件

三、代码实现

using UnityEngine;

using UnityEngine.UI;

/// <summary>

/// 实现镂空效果的Mask组件

/// </summary>

public class HollowOutMask : MaskableGraphic, ICanvasRaycastFilter

{

[SerializeField]

private RectTransform _target;

private Vector3 _targetMin = Vector3.zero;

private Vector3 _targetMax = Vector3.zero;

private bool _canRefresh = true;

private Transform _cacheTrans = null;

/// <summary>

/// 设置镂空的目标

/// </summary>

public void SetTarget(RectTransform target)

{

_canRefresh = true;

_target = target;

_RefreshView();

}

private void _SetTarget(Vector3 tarMin, Vector3 tarMax)

{

if (tarMin == _targetMin && tarMax == _targetMax)

return;

_targetMin = tarMin;

_targetMax = tarMax;

SetAllDirty();

}

private void _RefreshView()

{

if (!_canRefresh) return;

_canRefresh = false;

if (null == _target)

{

_SetTarget(Vector3.zero, Vector3.zero);

SetAllDirty();

}

else

{

Bounds bounds = RectTransformUtility.CalculateRelativeRectTransformBounds(_cacheTrans, _target);

_SetTarget(bounds.min, bounds.max);

}

}

protected override void OnPopulateMesh(VertexHelper vh)

{

if (_targetMin == Vector3.zero && _targetMax == Vector3.zero)

{

base.OnPopulateMesh(vh);

return;

}

vh.Clear();

// 填充顶点

UIVertex vert = UIVertex.simpleVert;

vert.color = color;

Vector2 selfPiovt = rectTransform.pivot;

Rect selfRect = rectTransform.rect;

float outerLx = -selfPiovt.x * selfRect.width;

float outerBy = -selfPiovt.y * selfRect.height;

float outerRx = (1 - selfPiovt.x) * selfRect.width;

float outerTy = (1 - selfPiovt.y) * selfRect.height;

// 0 - Outer:LT

vert.position = new Vector3(outerLx, outerTy);

vh.AddVert(vert);

// 1 - Outer:RT

vert.position = new Vector3(outerRx, outerTy);

vh.AddVert(vert);

// 2 - Outer:RB

vert.position = new Vector3(outerRx, outerBy);

vh.AddVert(vert);

// 3 - Outer:LB

vert.position = new Vector3(outerLx, outerBy);

vh.AddVert(vert);

// 4 - Inner:LT

vert.position = new Vector3(_targetMin.x, _targetMax.y);

vh.AddVert(vert);

// 5 - Inner:RT

vert.position = new Vector3(_targetMax.x, _targetMax.y);

vh.AddVert(vert);

// 6 - Inner:RB

vert.position = new Vector3(_targetMax.x, _targetMin.y);

vh.AddVert(vert);

// 7 - Inner:LB

vert.position = new Vector3(_targetMin.x, _targetMin.y);

vh.AddVert(vert);

// 设定三角形

vh.AddTriangle(4, 0, 1);

vh.AddTriangle(4, 1, 5);

vh.AddTriangle(5, 1, 2);

vh.AddTriangle(5, 2, 6);

vh.AddTriangle(6, 2, 3);

vh.AddTriangle(6, 3, 7);

vh.AddTriangle(7, 3, 0);

vh.AddTriangle(7, 0, 4);

}

bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 screenPos, Camera eventCamera)

{

if (null == _target) return true;

// 将目标对象范围内的事件镂空(使其穿过)

return !RectTransformUtility.RectangleContainsScreenPoint(_target, screenPos, eventCamera);

}

protected override void Awake()

{

base.Awake();

_cacheTrans = GetComponent<RectTransform>();

}

#if UNITY_EDITOR

void Update()

{

_canRefresh = true;

_RefreshView();

}

#endif

}

四、使用说明

将以上组件挂载到有RectTransform组件的游戏物体身上,设置Color的颜色以及Target区域的大小即可

——此组件挂载的游戏物体身上只能有一个继承Graphics类的组件

——若自定义添加Image控制Target区域大小,记得将Image的Alpha设置为0并且取消射线检测

以上是 Unity实现新手引导镂空效果 的全部内容, 来源链接: utcz.com/z/339204.html

回到顶部