欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Unity实现新手引导镂空效果

程序员文章站 2023-11-14 17:17:58
本文实例为大家分享了unity实现新手引导镂空效果的具体代码,供大家参考,具体内容如下一、实现思路创建有8个顶点的mesh,内外边界都是四边形(矩形)。只生成内、外边之间的mesh,内层矩形就产生了镂...

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。