我所实现的橡皮擦效果是设置图片某点的像素的透明度为0,来简单实现擦除效果的;

下面是效果

首先需要注意两点:1:设置 Main Camera 的 projection 属性为Orthographic

2:设置Canvas 的Render Mode 为 Screen Space - Camera

然后找一张图片,导入Unity 中并修改它的读写权限,创建Raw Imager

 

这样启动之后就可以测试效果了。

附上代码:(代码中有解释)

 using AYUI.UIFrame;
using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI; public class EraseMask : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{ //是否擦除了
public bool isStartEraser; //是否擦除结束了
public bool isEndEraser; //开始事件
public Action eraserStartEvent; //结束事件
public Action eraserEndEvent; public RawImage uiTex;
Texture2D tex;
Texture2D MyTex;
int mWidth;
int mHeight; [Header("Brush Size")]
public int brushSize = ; [Header("Rate")]
public int rate = ; float maxColorA;
float colorA; void Awake()
{
tex = (Texture2D)uiTex.mainTexture;
MyTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
mWidth = MyTex.width;
mHeight = MyTex.height; MyTex.SetPixels(tex.GetPixels());
MyTex.Apply();
uiTex.texture = MyTex;
maxColorA = MyTex.GetPixels().Length;
colorA = ;
isEndEraser = false;
isStartEraser = false; } /// <summary>
/// 贝塞尔平滑
/// </summary>
/// <param name="start">起点</param>
/// <param name="mid">中点</param>
/// <param name="end">终点</param>
/// <param name="segments">段数</param>
/// <returns></returns>
public Vector2[] Beizier(Vector2 start, Vector2 mid, Vector2 end, int segments)
{
float d = 1f / segments;
Vector2[] points = new Vector2[segments - ];
for (int i = ; i < points.Length; i++)
{
float t = d * (i + );
points[i] = ( - t) * ( - t) * mid + * t * ( - t) * start + t * t * end;
}
List<Vector2> rps = new List<Vector2>();
rps.Add(mid);
rps.AddRange(points);
rps.Add(end);
return rps.ToArray();
} bool startDraw = false;
bool twoPoints = false;
Vector2 lastPos;//最后一个点
Vector2 penultPos;//倒数第二个点
float radius = 12f;
float distance = 1f; #region 事件
public void OnPointerDown(PointerEventData eventData)
{
if (isEndEraser) { return; }
startDraw = true;
penultPos = eventData.position;
CheckPoint(penultPos);
} public void OnDrag(PointerEventData eventData)
{
if (isEndEraser) { return; }
if (twoPoints && Vector2.Distance(eventData.position, lastPos) > distance)//如果两次记录的鼠标坐标距离大于一定的距离,开始记录鼠标的点
{
Vector2 pos = eventData.position;
float dis = Vector2.Distance(lastPos, pos); CheckPoint(eventData.position);
int segments = (int)(dis / radius);//计算出平滑的段数
segments = segments < ? : segments;
if (segments >= ) { segments = ; }
Vector2[] points = Beizier(penultPos, lastPos, pos, segments);//进行贝塞尔平滑
for (int i = ; i < points.Length; i++)
{
CheckPoint(points[i]);
}
lastPos = pos;
if (points.Length > )
penultPos = points[points.Length - ];
}
else
{
twoPoints = true;
lastPos = eventData.position;
}
} public void OnPointerUp(PointerEventData eventData)
{
if (isEndEraser) { return; }
//CheckPoint(eventData.position);
startDraw = false;
twoPoints = false;
} #endregion void CheckPoint(Vector3 pScreenPos)
{
Vector3 worldPos = Camera.main.ScreenToWorldPoint(pScreenPos);
Vector3 localPos = uiTex.gameObject.transform.InverseTransformPoint(worldPos); if (localPos.x > -mWidth / && localPos.x < mWidth / && localPos.y > -mHeight / && localPos.y < mHeight / )
{
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, ) + Mathf.Pow(j - localPos.y, ) > Mathf.Pow(brushSize, ))
continue;
if (i < ) { if (i < -mWidth / ) { continue; } }
if (i > ) { if (i > mWidth / ) { continue; } }
if (j < ) { if (j < -mHeight / ) { continue; } }
if (j > ) { if (j > mHeight / ) { continue; } } Color col = MyTex.GetPixel(i + (int)mWidth / , j + (int)mHeight / );
if (col.a != 0f)
{
col.a = 0.0f;
colorA++;
MyTex.SetPixel(i + (int)mWidth / , j + (int)mHeight / , col);
}
}
} //开始刮的时候 去判断进度
if (!isStartEraser)
{
isStartEraser = true;
InvokeRepeating("getTransparentPercent", 0f, 0.2f);
if (eraserStartEvent != null)
eraserStartEvent.Invoke();
} MyTex.Apply();
}
} double fate; /// <summary>
/// 检测当前刮刮卡 进度
/// </summary>
/// <returns></returns>
public void getTransparentPercent()
{
if (isEndEraser) { return; } fate = colorA / maxColorA * ; fate = (float)Math.Round(fate, ); // Debug.LogError("当前百分比: " + fate); if (fate >= rate)
{
isEndEraser = true;
CancelInvoke("getTransparentPercent");
gameObject.SetActive(false); //触发结束事件
if (eraserEndEvent != null)
eraserEndEvent.Invoke(); }
} }

另附一张好用的图片 :https://pan.baidu.com/s/1Z_GTuwPouFtiSgVcFfrAcg

提取码:da7t

Unity 实现橡皮擦效果的更多相关文章

  1. 2015.4.25-2015.5.1 字符串去重,比例圆设计,中奖机和canvas橡皮擦效果等

    1.字符串去重,html模板取值   2.javascript正则表达式之$1...$9   3.jquery插件   4.返回上一页并刷新 解决方法: <a href ="javas ...

  2. unity传送门类似效果实现

    简述 在传送门中,核心的玩法是在地上或者墙上打开2个可以联通的洞来实现传送的效果.以此扩展加入解谜要素构成游戏的核心. 这里尝试使用unity来实现传送门的核心功能,具体功能分析如下: 1.传送门的模 ...

  3. Unity Shader - 消融效果原理与变体

    基本原理与实现 主要使用噪声和透明度测试,从噪声图中读取某个通道的值,然后使用该值进行透明度测试. 主要代码如下: fixed cutout = tex2D(_NoiseTex, i.uvNoiseT ...

  4. unity,荧光效果(bloom)实现过程

    两个月前,刚接触unity的时候费了半天劲儿做了个荧光效果(见:http://www.cnblogs.com/wantnon/p/4430749.html),今天终于抽空整理了一下,把过程写下来. 荧 ...

  5. 关于Unity中粒子效果的使用

    粒子效果1: 游戏中会有很炫酷的特效,比如爆炸,水花,火焰等;2: unity提供粒子编辑器,方便特效人员来开发很炫酷的特效;3.粒子效果一般有专门的粒子特效师来做,我们只需要拿来用就好了,很多参数没 ...

  6. unity 图片 粉碎效果 破碎效果

    效果: 点击按钮后: 这些碎片具有物理碰撞效果,下面会有隐形的支柱垫着碎片,n秒后支柱消失,碎片落下 当然你也可以控制生成的碎片,让他们从下而上一块一块地落下 插件源码: https://github ...

  7. Unity光晕剑效果的Shader简单实现

    最近遇到了一个需求,想要一种在刀剑上带有光晕的酷炫效果,甚至是还想要有闪烁呼吸效果,于是就写了一个简单的叫LightSwrod的Shader去实现,先上图看看效果吧. 简单展示 这是剑本身的样子 这是 ...

  8. Unity音乐喷泉效果

    本文参考了该文,其素材也取之于该处 效果 实现效果(根据音乐的高低会产生不同的波纹): 可以观看视频来获得更好的体验. 波纹的实现 先模拟出如下效果: 通过鼠标的点击,产生一个扩散的圆圈. 如上图所示 ...

  9. android 实现橡皮擦效果以及保存涂鸦的功能

    实现涂鸦.擦除.保存的功能 设置画笔为橡皮擦功能 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 如果你的画出来的是 ...

随机推荐

  1. SpringMVC利用AOP实现自定义注解记录日志

    作者:飞翔的拖鞋up 推荐:彻底征服 Spring AOP 之 实战篇 推荐:jason_zhangz 本文抛砖引玉,并没有详细的介绍更全面的内容,通过一个例子让初次使用的人能够快速入门,简单的介绍一 ...

  2. PHP mysqli_errno() 函数

    返回最近调用函数的最后一个错误代码: <?php // 假定数据库用户名:root,密码:123456,数据库:RUNOOB $con=mysqli_connect("localhos ...

  3. 基础数据类型-字符串str

    什么是字符串? 单引号,双引号,三引号包裹的文本 在我们的代码中换行区别 单/双引号:‘a’\ 'b' 三引号:"""a b""" 索引 s ...

  4. 利用Python爬取朋友圈数据,爬到你开始怀疑人生

    人生最难的事是自我认知,用Python爬取朋友圈数据,让我们重新审视自己,审视我们周围的圈子. 文:朱元禄(@数据分析-jacky) 哲学的两大问题:1.我是谁?2.我们从哪里来? 本文 jacky试 ...

  5. flask + nginx + uwsgi + ubuntu18.04部署python restful接口

    目录 参考链接 效果展示 一.准备工作 1.1 可运行的python demo: 1.2 更新系统环境 二.创建python虚拟环境 三.设置flask应用程序 四.配置uWSGI 五.设置系统启动 ...

  6. RuntimeException异常处理汇总

    Java中所有异常的父类是Throwable类,在Throwable类下有两大子类: 一个是Error类,指系统错误异常,例如:VirtualMachineError 虚拟机错误,ThreadDeat ...

  7. PHP多进程开发与Redis结合实践

    原文:https://blog.51cto.com/laok8/2107892?source=drh 业务逻辑介绍: 用户在 APP 上发帖子,然后存储到 Redis 的 List 列表中 利用 Li ...

  8. ThinkPHP6.0学习之项目安装页面的开发

    在我们做一个项目的时候,如果是自己用或者是给同行用的话往往不需要做一个安装页面的,但是如果是将项目给一些不怎么会操作服务器,不怎么会程序的人用的时候,我们就需要一个安装页面来帮助他们更好的将项目安装好 ...

  9. 高性能高可用的微服务框架TarsGo的腾讯实践

    conference/2.3 高性能高可用的微服务框架TarsGo的腾讯实践 - 陈明杰.pdf at master · gopherchina/conferencehttps://github.co ...

  10. Facebook币Libra学习-4.新的智能合约语言Move入门

    Move是一种新的编程语言,旨在为Libra Blockchain提供安全可编程的基础.Libra Blockchain中的帐户是任意数量的Move资源和Move模块的容器.提交给Libra Bloc ...