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


猜你喜欢
- 前言在这个系列博客的第二篇的最后部分提到了预布局,在预布局阶段,计算剩余空间时会把将要移除的 ViewHolder 忽略,从而计算出递补的
- 前言面向切面编程,利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发
- <?xml version="1.0" encoding="utf-8"?><Ed
- 本文实例讲述了android获取当前运行Activity名字的方法,可以避免即时聊天再出现通知的情况。分享给大家供大家参考。具体方法如下:最
- 出现乱码请修改为BufferedReader br = new BufferedReader(new InputStreamReader(n
- 一、背景spring-data-mongo 实现了基于 MongoDB 的 ORM-Mapping 能力,通过一些简单的注解、Query封装
- 本文实例为大家分享Winform版计算器的具体实现方法,供大家参考,具体内容如下前台页面设计后台代码实现using System;using
- 本文实例为大家分享了Android实现接近传感器的具体代码,供大家参考,具体内容如下1.接近传感器检测物体与听筒(手机)的距离,单位是厘米。
- 使用commons的jexl可实现将字符串变成可执行代码的功能,我写了一个类来封装这个功能:import java.util.Map;imp
- 本文实例为大家分享了C#支付宝新版支付请求接口调用的具体代码,供大家参考,具体内容如下因为支付宝已经集成了完整的SDK,所以可以使用SDK直
- 1、下载64位rxtx for java 链接:http://fizzed.com/oss/rxtx-for-java2、下载下来的包解压后
- 概述java移位符主要包括3种:运算符名称>>左移运算符<<有符号右移运算符<<<无符号右移运算符
- 最近做的项目有一个要求,就是在WebView中显示的html,需要在点击其中的图片时进行放大,并进行缩放和滑动 浏览,我第一想到的是这是和j
- 1、SSL介绍和说明SSL的配置也是我们在实际应用中经常遇到的场景SSL(Secure Sockets Layer,安全套接层)是为网络通信
- 函数式接口1.1 函数式接口概述函数式接口:有且仅有一个抽象方法的接口Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可
- 一,程序执行慢导致的原因就是查询数据库慢.,导致返回值慢,那这个要怎么解决呢?1,优化数据库查询如这个文章 C#导出数据到excel如何提升
- 实现Runnable 接口比继承Thread 类的方式更好:(1)可以避免由于Java单继承带来的局限性;(2)可以实现业务执行逻辑和数据资
- 之前有学弟问过我一道java的面试题,题目不算难。用java实现杨辉三角。我花了点时间整理了一下,发现挺有意思的,于是想写下来分享一下。在写
- 先通过idea或者eclipse也或者cmd把后缀java编译成class文件编译好的class文件,找到本地目录,运行cmd输入:jar
- 1.发生问题的场景我在用java获取一个接口的大JSON字符串,并赋值给String常量时,遇到了java: 常量字符串过长这个报错2.解决