当前位置: 移动技术网 > IT编程>开发语言>c# > Unity实现新手引导镂空效果

Unity实现新手引导镂空效果

2020年06月23日  | 移动技术网IT编程  | 我要评论

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

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网