Unity实现新手引导镂空效果

作者:LLLLL__ 时间:2022-07-04 22:50:23 

本文实例为大家分享了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并且取消射线检测

来源:https://blog.csdn.net/LLLLL__/article/details/104263122

标签:Unity,新手引导,镂空
0
投稿

猜你喜欢

  • C#生成word记录实例解析

    2023-09-10 00:17:33
  • Spring Boot 动态数据源示例(多数据源自动切换)

    2021-07-03 04:27:02
  • android实现简单的活动转盘

    2022-11-29 08:40:35
  • C# 定时器定时更新的简单实例

    2023-01-08 12:45:50
  • go打包aar及flutter调用aar流程详解

    2023-06-24 17:39:21
  • Java ArrayList实现删除指定位置的元素

    2023-11-25 05:34:13
  • Java实现淘宝秒杀聚划算抢购自动提醒源码

    2022-09-11 10:11:53
  • Entity Framework映射TPH、TPT、TPC与继承类

    2022-10-18 04:52:52
  • Android EditText长按菜单中分享功能的隐藏方法

    2021-08-27 19:30:45
  • Android 中在有序广播中添加自定义权限的实例

    2021-08-10 05:09:35
  • 解决SpringBoot框架因post数据量过大没反应问题(踩坑)

    2023-11-28 11:59:30
  • Java 类与对象超基础讲解

    2023-06-12 00:03:22
  • Java8生成时间方式及格式化时间的方法实例

    2021-07-28 19:58:52
  • JAVA Integer类常用方法解析

    2021-09-01 06:51:08
  • Springboot与vue实现文件导入方法具体介绍

    2023-10-31 12:31:37
  • SpringBoot+JWT实现注册、登录、状态续签流程分析

    2022-09-29 09:07:11
  • Spring @Import注解的使用

    2022-03-26 16:38:43
  • Android Framework如何实现Binder

    2021-12-09 03:54:20
  • VSCode中开发JavaWeb项目的详细过程(Maven+Tomcat+热部署)

    2022-10-18 14:42:10
  • Java关于桶排序的知识点总结

    2023-12-06 03:18:04
  • asp之家 软件编程 m.aspxhome.com