Unity实现新手引导镂空效果
程序员文章站
2023-11-14 17:17:58
本文实例为大家分享了unity实现新手引导镂空效果的具体代码,供大家参考,具体内容如下一、实现思路创建有8个顶点的mesh,内外边界都是四边形(矩形)。只生成内、外边之间的mesh,内层矩形就产生了镂...
本文实例为大家分享了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并且取消射线检测
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。