游戏蛮牛学习群(纯技术交流,不闲聊):539178957
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2286

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 4673|回复: 104

[大锅的案例] unity制作刮刮乐效果

  [复制链接]  [移动端链接]
排名
4206
昨日变化
4

16

主题

84

帖子

955

积分

Rank: 9Rank: 9Rank: 9

UID
97961
好友
5
蛮牛币
1373
威望
0
注册时间
2015-5-6
在线时间
481 小时
最后登录
2018-8-16
发表于 2018-1-22 20:30:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
网上看过了很多刮刮乐的文章,自己参考了一些,也改良了一些方法,比如说改良了画的每个点不连续的情况。具体效果如下:
123.gif

做出这种效果,其实挺简单,主要就是利用unity的render texture加上自己写的遮罩shader。
我们首先设置两个摄像机,一个是专门渲染render texture用的,让它只能看到笔刷图层,命名为brushCamera,并且要设为dont clear模式:
QQ截图20180122201436.png


QQ截图20180122200928.png

然后我们要创建一个笔刷预设体,这个笔刷预设体主要实现笔刷效果:
QQ截图20180122201138.png

下面的实现思路就是:当按下鼠标时,我们就克隆一个笔刷,这样就形成了涂画的效果。
然后我们写一个遮罩shader,shader中需要两张图,一张是遮罩的图片(就是图中的蓝色图片),另一张是用于剔除遮罩的图片,我们将渲染出的rendertexture作为剔除遮罩的图片。这样就完成了刮刮乐效果。

其中,我们要注意几个问题
1、由于当鼠标快速滑动时,可能会产生每个点不连续的情况,这里我们用了贝塞尔平滑方法进行处理。
2、大量克隆笔刷,会非常消耗性能,这里我们采用创建对象池方法的方法解决这个问题。
下面是主要的代码:
c#代码:

[C#] 纯文本查看 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DrawMask : MonoBehaviour {
    public float radius = 0.5f;//半径
    public GameObject brush;
    bool startDraw = false;
    bool twoPoints = false;
    Vector2 lastPos;//最后一个点
    Vector2 penultPos;//倒数第二个点
    List<GameObject> brushesPool = new List<GameObject>(),activeBrushes = new List<GameObject>();//笔刷对象池

    public delegate void DrawHandler(Vector2 pos);
    public event DrawHandler onStartDraw;
    public event DrawHandler onEndDraw;
    public event DrawHandler drawing;
    // Use this for initialization
    void Start () {
	}
	
	// Update is called once per frame
	void Update () {
         GetInput();

	}

    void GetInput()
    {
        if (Input.GetMouseButtonDown(0))
        {
            startDraw = true;
            if (onStartDraw != null)
            {
                onStartDraw(VectorTransfer(Input.mousePosition));
            }
            penultPos = Input.mousePosition;
        }
        else if (Input.GetMouseButton(0))
        {
            if (twoPoints && Vector2.Distance(Input.mousePosition,lastPos) > 0.5f)//如果两次记录的鼠标坐标距离大于一定的距离,开始记录鼠标的点
            {
                Vector2 pos = Input.mousePosition;
                float dis = Vector2.Distance(lastPos, pos);
                int segments = (int)(dis / radius);//计算出平滑的段数
                segments = segments < 1 ? 1 : segments;
                Vector2[] points = Beizier(penultPos, lastPos, pos, segments);//进行贝塞尔平滑
                for (int i = 0; i < points.Length; i++)
                {
                    InstanceBrush(VectorTransfer(points[i]));
                }
                if (drawing != null)
                {
                    drawing(VectorTransfer(Input.mousePosition));
                }
                lastPos = pos;
                penultPos = points[points.Length - 2];
            }
            else
            {
                twoPoints = true;
                lastPos = Input.mousePosition;
            }
        }
        else if (Input.GetMouseButtonUp(0))
        {
            if (onEndDraw != null)
            {
                onEndDraw(VectorTransfer(Input.mousePosition));
            }
            startDraw = false;
            twoPoints = false;
        }
    }

    private void OnPostRender()
    {
        InitBrushes();
    }

    void InitBrushes()
    {
        for (int i = 0; i < activeBrushes.Count; i++)
        {
            activeBrushes[i].SetActive(false);
            brushesPool.Add(activeBrushes[i]);
        }
        activeBrushes.Clear();
    }

    void InstanceBrush(Vector2 pos)
    {
        GameObject brushClone;
        if (brushesPool.Count > 0)
        {
            brushClone = brushesPool[brushesPool.Count - 1];
            brushesPool.RemoveAt(brushesPool.Count - 1);
        }
        else
        {
            brushClone = Instantiate(brush, pos, Quaternion.identity);
        }
        brushClone.transform.position = pos;

        brushClone.transform.localScale = Vector3.one * radius;
        brushClone.SetActive(true);
        activeBrushes.Add(brushClone);
    }

    /// <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 - 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 = new List<Vector2>();
        rps.Add(mid);
        rps.AddRange(points);
        rps.Add(end);
        return rps.ToArray(); 
    }

    Vector2 VectorTransfer(Vector2 point)
    {
        return Camera.main.ScreenToWorldPoint(new Vector3(point.x, point.y, 0));
    }
}



遮罩shader:
[C] 纯文本查看 复制代码
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/MaskShader" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		//_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_MaskTex("Mask Texture",2D) = "white"{}
		_Mask("Mask",2D) = "white"{}

	}
	SubShader {
		Tags{"RenderType" = "Transparent" "Queue" = "Transparent"}
		pass
		{
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "unitycg.cginc"

			struct v2f 
			{
				float4 pos:POSITION;
				float2 uv:TEXCOORD1;
			};

			//sampler2D _MainTex;
			sampler2D _MaskTex;
			sampler2D _Mask;

			v2f vert(appdata_base v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				return o;
			}

			float4 frag(v2f i):COLOR
			{
				//float4 mainColor = tex2D(_MainTex,i.uv);
				float4 maskTexColor = tex2D(_MaskTex,i.uv);
				float4 maskColor = tex2D(_Mask,i.uv);
				maskTexColor.a = 1 - maskColor.a;
				return maskTexColor;
			}
			ENDCG
		}
	}
	FallBack "Diffuse"
}



项目源码:
guaguale.rar (6.29 MB, 下载次数: 2279, 售价: 2 蛮牛币)

点评

感谢分享,请问如何知道刮了多大面积呢  发表于 2018-7-20 15:22

评分

参与人数 7鲜花 +25 收起 理由
chris21129 + 2 赞一个!
copylightlee + 2 很给力!
凡水 + 4 赞一个!
lilexy + 5 赞一个!
海峡同城哥 + 5 赞一个!
研究者 + 5 很给力!
侯大人 + 2 赞一个!

查看全部评分


回复

使用道具 举报

7日久生情
2536/5000
排名
3502
昨日变化
3

2

主题

1780

帖子

2536

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
241666
好友
0
蛮牛币
10199
威望
0
注册时间
2017-9-6
在线时间
362 小时
最后登录
2018-6-7
发表于 2018-1-23 07:42:24 来自Mobile--- | 显示全部楼层
感谢分享

回复

使用道具 举报

7日久生情
1524/5000
排名
2595
昨日变化
12

54

主题

379

帖子

1524

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
119735
好友
1
蛮牛币
17311
威望
0
注册时间
2015-8-26
在线时间
589 小时
最后登录
2018-8-16
发表于 2018-1-23 08:24:51 | 显示全部楼层
感谢分享

回复

使用道具 举报

7日久生情
2931/5000
排名
341
昨日变化

1

主题

682

帖子

2931

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
27356
好友
1
蛮牛币
4246
威望
0
注册时间
2014-5-30
在线时间
586 小时
最后登录
2018-8-16
发表于 2018-1-23 09:08:27 | 显示全部楼层
有意思,图片更有意思 :)

回复 支持 反对

使用道具 举报

7日久生情
1699/5000
排名
1371
昨日变化
6

18

主题

206

帖子

1699

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
172976
好友
4
蛮牛币
541
威望
0
注册时间
2016-9-30
在线时间
641 小时
最后登录
2018-8-16
发表于 2018-1-23 09:12:46 | 显示全部楼层
厉害了

回复

使用道具 举报

7日久生情
4203/5000
排名
2660
昨日变化
2

5

主题

3111

帖子

4203

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
209186
好友
5
蛮牛币
5250
威望
0
注册时间
2017-3-1
在线时间
591 小时
最后登录
2018-8-14
发表于 2018-1-23 09:18:54 | 显示全部楼层
谢谢分享

回复

使用道具 举报

7日久生情
2225/5000
排名
3097
昨日变化
13

8

主题

1105

帖子

2225

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
168159
好友
4
蛮牛币
5117
威望
0
注册时间
2016-9-12
在线时间
668 小时
最后登录
2018-8-16
发表于 2018-1-23 09:19:05 | 显示全部楼层

回复

使用道具 举报

7日久生情
1791/5000
排名
2433
昨日变化
6

43

主题

740

帖子

1791

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
219600
好友
7
蛮牛币
2401
威望
0
注册时间
2017-4-27
在线时间
470 小时
最后登录
2018-8-16
发表于 2018-1-23 09:27:41 | 显示全部楼层
厉害了,感谢分享

回复

使用道具 举报

5熟悉之中
516/1000
排名
4939
昨日变化
4

0

主题

140

帖子

516

积分

Rank: 5Rank: 5

UID
241750
好友
0
蛮牛币
949
威望
0
注册时间
2017-9-6
在线时间
112 小时
最后登录
2018-3-26
发表于 2018-1-23 09:29:37 | 显示全部楼层
66666666666666666666666666666666666666666

回复 支持 反对

使用道具 举报

7日久生情
1881/5000
排名
1721
昨日变化
2

34

主题

630

帖子

1881

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
174225
好友
1
蛮牛币
108
威望
0
注册时间
2016-10-9
在线时间
511 小时
最后登录
2018-8-15
QQ
发表于 2018-1-23 09:30:50 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
587/1000
排名
5669
昨日变化
4

0

主题

113

帖子

587

积分

Rank: 5Rank: 5

UID
151151
好友
0
蛮牛币
920
威望
0
注册时间
2016-6-7
在线时间
251 小时
最后登录
2018-7-12
QQ
发表于 2018-1-23 09:32:58 | 显示全部楼层
感谢分享

回复

使用道具 举报

6蛮牛粉丝
1075/1500
排名
3451
昨日变化
4

1

主题

395

帖子

1075

积分

Rank: 6Rank: 6Rank: 6

UID
173098
好友
0
蛮牛币
4
威望
0
注册时间
2016-9-30
在线时间
285 小时
最后登录
2018-8-16
发表于 2018-1-23 09:33:34 | 显示全部楼层
谢谢。。。。。。。。。。。。。。。。。。。。。。。

回复

使用道具 举报

5熟悉之中
605/1000
排名
6487
昨日变化
45

2

主题

251

帖子

605

积分

Rank: 5Rank: 5

UID
229218
好友
1
蛮牛币
755
威望
0
注册时间
2017-6-28
在线时间
166 小时
最后登录
2018-8-15
发表于 2018-1-23 09:43:40 | 显示全部楼层
谢谢分享 有意思

回复

使用道具 举报

4四处流浪
318/500
排名
7471
昨日变化
4

0

主题

107

帖子

318

积分

Rank: 4

UID
248343
好友
0
蛮牛币
597
威望
0
注册时间
2017-10-12
在线时间
59 小时
最后登录
2018-5-10
发表于 2018-1-23 09:51:04 | 显示全部楼层
v5v5v5v5v5v5v5v5

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1374/1500
排名
1933
昨日变化

3

主题

94

帖子

1374

积分

Rank: 6Rank: 6Rank: 6

UID
35774
好友
1
蛮牛币
1870
威望
0
注册时间
2014-7-22
在线时间
633 小时
最后登录
2018-8-2
发表于 2018-1-23 09:52:22 | 显示全部楼层
用GL来,性能会几何级提升

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表