我所实现的橡皮擦效果是设置图片某点的像素的透明度为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. npm常规操作

    1.如果想在当前文件下创建package.json,只要在当前目录下执行npm init 2.如果执行过程中缺少依赖,有两种途径 ①安装全局 npm install -g express ②在当前工程 ...

  2. python 获取指定字符前面或后面的所有字符

    要求:获取某个字符指定字符的前面或后面的所有字符内容 示例: URL = https://www.baid/v2/user/login (1)想要获取v2的数据:v2/user/login print ...

  3. 第92题:反转链表II

    一. 问题描述 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NUL ...

  4. //点击按钮加减音频音量到最小会出现bug什么意思???

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. position:absolute 按钮左右分布:left:0 和 right:0 以及雪碧图

    问题:把两个a标签按钮 垂直居中,并且分别把两个按钮放在水平左右两边顶部1,祖父元素设定:position:relative2,把.arrow 设定上下垂直居中 position:absolute; ...

  6. 应用webservice实现公网天气查询

    1. wsdl网址:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl 2. URL:http://www.webxml.com.cn/zh ...

  7. 用HTML5里的window.postMessage在两个网页间传递数据

    说明 window.postMessage()方法可以安全地实现Window对象之间的跨域通信.例如,在一个页面和它生成的弹出窗口之间,或者是页面和嵌入其中的iframe之间. 通常情况下,不同页面上 ...

  8. Git Clone 的时候遇到 Filename too long 错误

    在对某些仓库进行 Git Clone 的时候遇到了 Filename too long 的错误提示. 错误提示如下图: 可以有下面的一些解决办法: 可以有下面的一些解决办法: 在 Git bash 中 ...

  9. JAVA RPC 生产级高可用RPC框架使用分享

    先放出链接,喜欢的给个star:https://gitee.com/a1234567891/koalas-rpc 一:项目介绍 koalas-RPC 个人作品,提供大家交流学习,有意见请私信,欢迎拍砖 ...

  10. 以太坊geth区块链私链建立

      以太坊geth区块链私链建立 geth的github https://github.com/ethereum/go-ethereum 下载最新(1.8)的geth,windows下安装很简单 关于 ...