0


【Unity3D小功能】Unity3D中实现UI擦除效果、刮刮卡功能

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • 我的个人博客

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

使用Unity3D实现UI的擦拭效果、刮刮卡功能的效果实现方式比较多,比如说用Shader、Texture渲染都是可以的。

本篇文章就使用Texture渲染来实现擦除的效果,效果图如下:

在这里插入图片描述
接下来就来看一下如何实现吧。

二、正文

2-1、实现原理

(1)取得遮罩图的像素数据。
(2)在鼠标滑动的时候,将屏幕坐标转换到遮罩在父节点下的坐标。
(3)以鼠标点击的点为中心,生成需要擦除的区域大小,通过与记录的遮罩数据进行对比,替换擦除的区域的像素值。
(4)计算每一个像素的alpha值,设置为0,达到透明的效果。
(5)拖动的话使用了贝塞尔平滑,让擦除更加的丝滑。

2-2、实现步骤

(1)设置摄像机的属性
在这里插入图片描述

Projection

设置为

Orthographic

(2)新建一个Canvas,设置属性:
在这里插入图片描述

Render Mode

Screen Space-Camera
Render Camera

摄像机对象
UI Scale Mode

Scale With Screen Size
Reference Resolution

1920 * 1080

(3)新建一个Image,再新建一个RawImage
在这里插入图片描述
在这里插入图片描述
底板和蒙版的图:
在这里插入图片描述

在这里插入图片描述
(4)新建脚本命名为EraseMask.cs,双击打开脚本,修改脚本:

usingSystem;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.EventSystems;usingUnityEngine.UI;publicclassEraseMask:MonoBehaviour,IPointerDownHandler,IDragHandler,IPointerUpHandler{[Header("是否启用")]publicbool isEnable =true;//是否启用[Header("毛刷大小")]publicint brushSize =50;//毛刷大小[Header("擦拭比例")]publicint rate =90;//可以设置当到达一定比例后全部显示Action eraserEvent;//擦拭事件RawImage uiTex;//渲染对象Texture2D MyTex;//渲染材质int mWidth, mHeight;//宽,高int maxColor, startColor;//最大颜色量,开始颜色量bool twoPoints =false;//判断鼠标是否松开Vector2 startPos, endPos;//开始点,结束点float radius =12f;//平滑的段数float distance =1f;//鼠标滑动的距离double fate;//进度voidAwake(){if(!isEnable){return;}
        uiTex =GetComponentInChildren<RawImage>();Texture2D tex =(Texture2D)uiTex.mainTexture;
        MyTex =newTexture2D(tex.width, tex.height, TextureFormat.ARGB32,false);
        mWidth = MyTex.width;
        mHeight = MyTex.height;
        MyTex.SetPixels(tex.GetPixels());
        MyTex.Apply();
        uiTex.texture = MyTex;
        maxColor = MyTex.GetPixels().Length;
        startColor =0;
        eraserEvent += getTransparentPercent;}#region 事件publicvoidOnPointerDown(PointerEventData eventData){if(!isEnable){return;}
        startPos = eventData.position;CheckPoint(startPos);}publicvoidOnDrag(PointerEventData eventData){if(!isEnable){return;}if(twoPoints && Vector2.Distance(eventData.position, endPos)> distance)//如果两次记录的鼠标坐标距离大于一定的距离,开始记录鼠标的点{Vector2 pos = eventData.position;float dis = Vector2.Distance(endPos, pos);CheckPoint(eventData.position);int segments =(int)(dis / radius);//计算出平滑的段数                                              
            segments = segments <1?1: segments;if(segments >=10){ segments =10;}Vector2[] points =Beizier(startPos, endPos, pos, segments);//进行贝塞尔平滑for(int i =0; i < points.Length; i++){CheckPoint(points[i]);}
            endPos = pos;if(points.Length >2)
                startPos = points[points.Length -2];}else{
            twoPoints =true;
            endPos = eventData.position;}}publicvoidOnPointerUp(PointerEventData eventData){if(!isEnable){return;}
        twoPoints =false;}voidCheckPoint(Vector3 pScreenPos){Vector3 worldPos = Camera.main.ScreenToWorldPoint(pScreenPos);Vector3 localPos = uiTex.gameObject.transform.InverseTransformPoint(worldPos);if(localPos.x >-mWidth /2&& localPos.x < mWidth /2&& localPos.y >-mHeight /2&& localPos.y < mHeight /2){for(int i =(int)localPos.x - brushSize; i <(int)localPos.x + brushSize; i++){for(int j =(int)localPos.y - brushSize; j <(int)localPos.y + brushSize; j++){if(Mathf.Pow(i - localPos.x,2)+ Mathf.Pow(j - localPos.y,2)> Mathf.Pow(brushSize,2))continue;if(i <0){if(i <-mWidth /2){continue;}}if(i >0){if(i > mWidth /2){continue;}}if(j <0){if(j <-mHeight /2){continue;}}if(j >0){if(j > mHeight /2){continue;}}Color col = MyTex.GetPixel(i +(int)mWidth /2, j +(int)mHeight /2);if(col.a !=0f){
                        col.a =0.0f;
                        startColor++;
                        MyTex.SetPixel(i +(int)mWidth /2, j +(int)mHeight /2, col);}}}//开始刮的时候 去判断进度if(isEnable){
                eraserEvent.Invoke();}
            MyTex.Apply();}}#endregion/// <summary> /// 检测当前刮刮卡 进度/// </summary>/// <returns></returns>publicvoidgetTransparentPercent(){if(!isEnable){return;}
        fate =(float)startColor / maxColor *100;
        fate =(float)Math.Round(fate,2);
        Debug.Log("当前百分比: "+ fate);if(fate >= rate){
            isEnable =false;
            uiTex.gameObject.SetActive(false);}}/// <summary>/// 贝塞尔平滑/// </summary>/// <param name="start">起点</param>/// <param name="mid">中点</param>/// <param name="end">终点</param>/// <param name="segments">段数</param>/// <returns></returns>publicVector2[]Beizier(Vector2 start,Vector2 mid,Vector2 end,int segments){float d =1f/ segments;Vector2[] points =newVector2[segments -1];for(int i =0; i < points.Length; i++){float t = d *(i +1);
            points[i]=(1- t)*(1- t)* mid +2* t *(1- t)* start + t * t * end;}List<Vector2> rps =newList<Vector2>();
        rps.Add(mid);
        rps.AddRange(points);
        rps.Add(end);return rps.ToArray();}}

将脚本附到Canvas对象上:
在这里插入图片描述
(4)运行程序
在这里插入图片描述

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:
专栏方向简介Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

标签: ui unity 游戏引擎

本文转载自: https://blog.csdn.net/q764424567/article/details/130370931
版权归原作者 恬静的小魔龙 所有, 如有侵权,请联系我们删除。

“【Unity3D小功能】Unity3D中实现UI擦除效果、刮刮卡功能”的评论:

还没有评论