【你问我答】unity实现一个刮刮乐效果

这篇具有很好参考价值的文章主要介绍了【你问我答】unity实现一个刮刮乐效果。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

点关注不迷路,持续输出干货文章。

嗨,大家好,我是向宇。
之前有小伙伴对我提了一个问题,想要做一个image上鼠标拖动,能改变透明度的效果
unity 刮刮乐,你问我答,unity,游戏引擎
我们先来看看视频效果
unity 刮刮乐,你问我答,unity,游戏引擎
其实这个无疑就是一个刮刮乐的效果
本文我实现了两种效果,最终效果如下:
unity 刮刮乐,你问我答,unity,游戏引擎
unity 刮刮乐,你问我答,unity,游戏引擎

工程源码见文章末尾。

二、原理

原理就是利用Alpha通道,Alpha为0时透明,我们可以使用一张RenderTexture作为Alpha通道图,与UI的主贴图的Alpha通道图相乘即可。
根据鼠标刮的位置,在RenderTexture上对应的位置画笔刷印记即可。

三、实操

1.安装环境

新建项目,安装ShaderGraph和升级URP项目
unity 刮刮乐,你问我答,unity,游戏引擎

unity 刮刮乐,你问我答,unity,游戏引擎
具体如何升级URP可以看我之前写的文章:
项目的设置和导入及渲染管线的安装修复

2. 渲染纹理RenderTexture

首先,创建一个渲染纹理

unity 刮刮乐,你问我答,unity,游戏引擎
设置一下Render Texture的尺寸和格式
unity 刮刮乐,你问我答,unity,游戏引擎
用photoshop做两张图,一张纯黑色的方图(用于初始化填充Render Texture),一张笔刷图,简单起见,笔刷图案我就用一个白点。
如下:
unity 刮刮乐,你问我答,unity,游戏引擎

3.写脚本:ScratchUI.cs

代码的注释我写得比较清晰了,大家应该能看懂

// ScratchUI.cs

using UnityEngine;
using UnityEngine.EventSystems;


/// <summary>
/// 刮刮乐UI
/// </summary>
public class ScratchUI : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    /// <summary>
    /// 绘制的目标图片
    /// </summary>
    public RenderTexture renderTexture;
    /// <summary>
    /// 笔刷
    /// </summary>
    public Texture brushTexture;

    /// <summary>
    /// 空白图
    /// </summary>
    public Texture blankTexture;

    /// <summary>
    /// mask的RectTransform
    /// </summary>
    public RectTransform rectTransform;
    /// <summary>
    /// 画布
    /// </summary>
    public Canvas canvas;

    private bool m_isMove = false;

    private void Start()
    {
        DrawBlank();
    }

    /// <summary>
    /// 初始化RenderTexture
    /// </summary>
    private void DrawBlank()
    {
        // 激活rt
        RenderTexture.active = renderTexture;
        // 保存当前状态
        GL.PushMatrix();
        // 设置矩阵
        GL.LoadPixelMatrix(0, renderTexture.width, renderTexture.height, 0);

        // 绘制贴图
        Rect rect = new Rect(0, 0, renderTexture.width, renderTexture.height);
        Graphics.DrawTexture(rect, blankTexture);

        // 弹出改变
        GL.PopMatrix();

        RenderTexture.active = null;
    }

    /// <summary>
    /// 在RenderTexture的(x,y)坐标处画笔刷图案
    /// </summary>
    /// <param name="x">Graphics坐标系下的x</param>
    /// <param name="y">Graphics坐标系下的y</param>
    private void Draw(int x, int y)
    {
        // 激活rt
        RenderTexture.active = renderTexture;
        // 保存当前状态
        GL.PushMatrix();
        // 设置矩阵
        GL.LoadPixelMatrix(0, renderTexture.width, renderTexture.height, 0);


        // 绘制笔刷图案
        x -= (int)(brushTexture.width * 0.5f);
        y -= (int)(brushTexture.height * 0.5f);
        Rect rect = new Rect(x, y, brushTexture.width, brushTexture.height);
        Graphics.DrawTexture(rect, brushTexture);

        // 弹出改变
        GL.PopMatrix();

        RenderTexture.active = null;
    }

    /// <summary>
    /// 按下
    /// </summary>
    public void OnPointerDown(PointerEventData data)
    {
        m_isMove = true;
    }

    /// <summary>
    /// 抬起
    /// </summary>
    public void OnPointerUp(PointerEventData data)
    {
        m_isMove = false;
    }

    private void Update()
    {
        if (m_isMove)
        {
            OnMouseMove(Input.mousePosition);
        }
    }

    /// <summary>
    /// 刮卡
    /// </summary>
    /// <param name="position">刮卡的屏幕坐标</param>
    private void OnMouseMove(Vector2 position)
    {
        // 获取刮的位置的ui局部坐标
        var uiLocalPos = ScreenPosToUiLocalPos(position, rectTransform, canvas.worldCamera);
        // 将局部坐标转化为uv坐标
        var uvX = (rectTransform.sizeDelta.x / 2f + uiLocalPos.x) / rectTransform.sizeDelta.x;
        var uvY = (rectTransform.sizeDelta.y / 2f + uiLocalPos.y) / rectTransform.sizeDelta.y;
        // 将uv坐标转化为Graphics坐标
        var x = (int)(uvX * renderTexture.width);
        // 注意,uv坐标系和Graphics坐标系的y轴方向相反
        var y = (int)(renderTexture.height - uvY * renderTexture.height);

        Draw(x, y);
    }

    /// <summary>
    /// 将屏幕坐标抓话为目标RectTransform的局部坐标
    /// </summary>
    /// <param name="screenPos">屏幕坐标</param>
    /// <param name="transform">目标RectTransform</param>
    /// <param name="cam">摄像机</param>
    /// <returns>ui局部坐标</returns>
    private Vector2 ScreenPosToUiLocalPos(Vector3 screenPos, RectTransform transform, Camera cam)
    {
        Vector2 uiLocalPos;

        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(transform, screenPos, cam, out uiLocalPos))
        {
            return uiLocalPos;
        }
        return Vector2.zero;
    }
}

4.ShaderGraph

创建一个Unlit ShaderGraph,实现UI主贴图的Alpha通道与和RenderTexture的相乘。
unity 刮刮乐,你问我答,unity,游戏引擎
注意Graph Settings设置Surface为Transparent,Blend设置为Alpha。
unity 刮刮乐,你问我答,unity,游戏引擎
暴露出两个变量,方便在材质球中设置参数。
unity 刮刮乐,你问我答,unity,游戏引擎

5. UI制作

准备刮刮乐的UI图片,导入Unity中
unity 刮刮乐,你问我答,unity,游戏引擎
unity 刮刮乐,你问我答,unity,游戏引擎
拼成界面,如下。mask层就是要被刮掉的层。text可以写文字,比如恭喜中奖之类的
unity 刮刮乐,你问我答,unity,游戏引擎
新建一个摄像机,用于渲染UI
unity 刮刮乐,你问我答,unity,游戏引擎
最终效果
unity 刮刮乐,你问我答,unity,游戏引擎

6.材质球

创建一个材质球ScratchMaterial,使用上面做的ShaderGraph,给材质球赋值贴图。
unity 刮刮乐,你问我答,unity,游戏引擎
unity 刮刮乐,你问我答,unity,游戏引擎
最后将材质赋给mask的Material。
unity 刮刮乐,你问我答,unity,游戏引擎

7.挂脚本

将ScratchUI.cs脚本挂到mask上,并设置好参数。
RenderTexture:用于Alpha通道图;
Brush Texture:笔刷图案,一个白点;
Blank Texture:一张纯黑色的空白图;
RectTransform:mask的RectTransform,用于坐标转换;
Canvas:用于坐标转换。
unity 刮刮乐,你问我答,unity,游戏引擎

四、运行测试

unity 刮刮乐,你问我答,unity,游戏引擎

五、不同素材实现相同的效果

这是网友提供的素材
unity 刮刮乐,你问我答,unity,游戏引擎
unity 刮刮乐,你问我答,unity,游戏引擎
新建材质做相应的修改
unity 刮刮乐,你问我答,unity,游戏引擎

其他照旧
unity 刮刮乐,你问我答,unity,游戏引擎
最终效果
unity 刮刮乐,你问我答,unity,游戏引擎

源码

本文Demo工程已上传到git,感兴趣的同学可自行下载学习。
https://gitcode.net/unity1/guagua
注意,我使用的Unity版本是2021版

参考

【文章】:【游戏开发实战】使用Unity ShaderGraph实现刮刮乐的刮卡剔除效果,感受一下刮中500万的时刻

完毕

好了,我是向宇,https://xiangyu.blog.csdn.net/

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是开始自习unity。最近创建了一个新栏目【你问我答】,主要是想收集一下大家的问题,有时候一个问题可能几句话说不清楚,我就会以发布文章的形式来回答。 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~文章来源地址https://www.toymoban.com/news/detail-721670.html

到了这里,关于【你问我答】unity实现一个刮刮乐效果的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包