Unity 实现橡皮擦效果
我所实现的橡皮擦效果是设置图片某点的像素的透明度为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 实现橡皮擦效果的更多相关文章
- 2015.4.25-2015.5.1 字符串去重,比例圆设计,中奖机和canvas橡皮擦效果等
1.字符串去重,html模板取值 2.javascript正则表达式之$1...$9 3.jquery插件 4.返回上一页并刷新 解决方法: <a href ="javas ...
- unity传送门类似效果实现
简述 在传送门中,核心的玩法是在地上或者墙上打开2个可以联通的洞来实现传送的效果.以此扩展加入解谜要素构成游戏的核心. 这里尝试使用unity来实现传送门的核心功能,具体功能分析如下: 1.传送门的模 ...
- Unity Shader - 消融效果原理与变体
基本原理与实现 主要使用噪声和透明度测试,从噪声图中读取某个通道的值,然后使用该值进行透明度测试. 主要代码如下: fixed cutout = tex2D(_NoiseTex, i.uvNoiseT ...
- unity,荧光效果(bloom)实现过程
两个月前,刚接触unity的时候费了半天劲儿做了个荧光效果(见:http://www.cnblogs.com/wantnon/p/4430749.html),今天终于抽空整理了一下,把过程写下来. 荧 ...
- 关于Unity中粒子效果的使用
粒子效果1: 游戏中会有很炫酷的特效,比如爆炸,水花,火焰等;2: unity提供粒子编辑器,方便特效人员来开发很炫酷的特效;3.粒子效果一般有专门的粒子特效师来做,我们只需要拿来用就好了,很多参数没 ...
- unity 图片 粉碎效果 破碎效果
效果: 点击按钮后: 这些碎片具有物理碰撞效果,下面会有隐形的支柱垫着碎片,n秒后支柱消失,碎片落下 当然你也可以控制生成的碎片,让他们从下而上一块一块地落下 插件源码: https://github ...
- Unity光晕剑效果的Shader简单实现
最近遇到了一个需求,想要一种在刀剑上带有光晕的酷炫效果,甚至是还想要有闪烁呼吸效果,于是就写了一个简单的叫LightSwrod的Shader去实现,先上图看看效果吧. 简单展示 这是剑本身的样子 这是 ...
- Unity音乐喷泉效果
本文参考了该文,其素材也取之于该处 效果 实现效果(根据音乐的高低会产生不同的波纹): 可以观看视频来获得更好的体验. 波纹的实现 先模拟出如下效果: 通过鼠标的点击,产生一个扩散的圆圈. 如上图所示 ...
- android 实现橡皮擦效果以及保存涂鸦的功能
实现涂鸦.擦除.保存的功能 设置画笔为橡皮擦功能 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 如果你的画出来的是 ...
随机推荐
- Spring整合rabbitmq(转载)
原文地址:https://my.oschina.net/never/blog/140368 1.首先是生产者配置 <?xml version="1.0" encoding=& ...
- redis事务机制
目录 一.事务的实现 1.multi——开启事务 2.命令入队列 3.exec——执行事务 4.DISCARD——放弃执行 5.错误处理 二.watch命令 redis官方文档:Redis trans ...
- 多线程锁:Mutex互斥体,Semaphore信号量,Monitor监视器,lock,原子操作InterLocked
Mutex类 “mutex”是术语“互相排斥(mutually exclusive)”的简写形式,也就是互斥量.互斥量跟临界区中提到的Monitor很相似,只有拥有互斥对象的线程才具有访问资源的权限, ...
- C# 截图不失真
Bitmap bmp = new Bitmap(@"E:\2222.jpg"); Bitmap bmp2 = bmp.Clone(new Rectangle(10 + 80, 15 ...
- Java Part 001( 02_01_理解面向对象 )
Java完全支持面向对象的三个基本特征: 继承.封装.多态 面向对象的方式实际上由OOA(面向对象分析).OOD(面向对象设计).OOP(面向对象编程)三个部分有机组成 目前业界统一采用UML(统一建 ...
- 字节(byte)、二进制、字节流、字符流相关概念分析
https://blog.csdn.net/changwilling/article/details/52065955 1.字节: 字(Byte)节是长度单位.位(bit)也是长度单位. 因为计算机通 ...
- 查看文件被哪个进程lock住
How do you know who or what is locking a remote file? http://serverfault.com/questions/1948/how-do-y ...
- 【概率论】4-1:随机变量的期望(The Expectation of a Random Variable Part II)
title: [概率论]4-1:随机变量的期望(The Expectation of a Random Variable Part II) categories: - Mathematic - Pro ...
- CSS定位中“父相子绝”
一.定位的介绍 定位有三种:相对定位(position:relative).绝对定位(position:absolute).固定定位(position:fixed) 二.三种定位的用法,特点和实例 2 ...
- PHP 之验证码类封装
一.效果图 二.类代码 <?php /** * Created by PhpStorm. * User: Yang * Date: 2019/8/13 * Time: 10:51 */ clas ...