• 📢 welcome to like 👍 collect ⭐ message 📝 if there is an error please correct!
  • 📢 This article was originally written by dumb code Y at 🙉
  • 📢 The future is long and worth striving for a better life ✨


📢 preface

  • A few days ago a big brother: lonely cold using HTML to do a scratch-off music, we all quite like to see!

  • I thought it was fun, so I figured I could do it with Unity. Unity is an easy game engine to get started with

  • After making it can be packaged directly to other little brother little sister directly on the phone to play!!

  • Then to briefly say how to achieve such a scratch-off small case bar, only need a script can be completed ~

  • This article will be from a novice’s point of view complete the whole process will be written out! Old hands directly look at the script hanging!

  • If you haven’t worked with Unity before, this is your chance to get stuck!


🎬 only use a script to do a scratch, accidentally blow out a girlfriend!


🏳️🌈 Step 1: Open Unity and create a new project

Since we are doing this small project in Unity, the first step is to create a new project!

If you don’t know what the Unity engine is, it’s a bit out of date

Here is a free Unity learning column, including how to download and install Unity and configure the basic environment!

Learn the basics of Unity and Unity from a simple perspective!

Open theUnityHubCreate a newprojectChange the projectThe name of theandThe pathAnd then clickcreate.

Once created, a default is displayedUnityEmpty scene, maybe the window display position is not the same, you can adjust at will, this is not important ~


🏳️🌈 Step 2: Create an Image Image and RawImage Image

Right-click in the Hierarchy panel to create an Image and a RawImage

As shown in the figure below, you only need to understand these twoImage componentsAre used to display the picture of the component is OK ~ want to learn more can go to the column to learn oh!Then adjust these two images to the same size as the Canvas!

Click Image first, and then adjust the Image to Canvas size as shown below

You can also manually adjust the Image Image to the Canvas size!Image is the same as RawImage and I’m going to set it, and thenscenarioThe middle becomes the following!


🏳️🌈 Step 3: Adjust the camera and canvas modes

First select the Camera Camera, CameraProjection modeltoorthogonalJust change thisProjectionSettings, as shown below!Then select Canvas Canvas and change it to Canvas mode 2, as shown below:The concept of Canvas is as follows:And that’s not the end of itZoom modeChange to the second

Scale the screen size, set the resolution to 1920*1080, and mount the Main Camera onto the Canvas!

As shown below.


🏳️🌈 Step 4: Write a script and mount it to the Canvas

The above steps are to make the picture display more beautiful and in place, this step is the most critical step of the scratch-off!

Create a new C# script and copy the following code into the script

Go straight to code

using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class Demo: MonoBehaviour.IPointerDownHandler.IDragHandler.IPointerUpHandler
{
    // Whether to erase
    public bool isStartEraser;
    // Whether erasure is finished
    public bool isEndEraser;
    // Start the event
    public Action eraserStartEvent;
    // End the event
    public Action eraserEndEvent;
    public RawImage uiTex;
    Texture2D tex;
    Texture2D MyTex;
    int mWidth;
    int mHeight;
    [Header("Brush size")]
    public int brushSize = 50;
    [Header("Scratch-off ratio.")]
    public int rate = 90;
    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 = 0;
        isEndEraser = false;
        isStartEraser = false;
    }
    /// <summary>
    ///Bessel smoothing
    /// </summary>
    /// <param name="start">The starting point</param>
    /// <param name="mid">midpoint</param>
    /// <param name="end">At the end of</param>
    /// <param name="segments">Section number</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();
    }
    bool startDraw = false;
    bool twoPoints = false;
    Vector2 lastPos;// Last point
    Vector2 penultPos;// The penultimate point
    float radius = 12f;
    float distance = 1f;
    #regionThe event
    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)// If the distance between the two mouse coordinates is greater than a certain distance, start recording the mouse point
        {
            Vector2 pos = eventData.position;
            float dis = Vector2.Distance(lastPos, pos);

            CheckPoint(eventData.position);
            int segments = (int)(dis / radius);// Calculate the number of smooth segments
            segments = segments < 1 ? 1 : segments;
            if (segments >= 10) { segments = 10; }
            Vector2[] points = Beizier(penultPos, lastPos, pos, segments);// Perform Bessel smoothing
            for (int i = 0; i < points.Length; i++)
            {
                CheckPoint(points[i]);
            }
            lastPos = pos;
            if (points.Length > 2)
                penultPos = points[points.Length - 2];
        }
        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 / 2 && localPos.x < mWidth / 2 && localPos.y > -mHeight / 2 && localPos.y < mHeight / 2)
        {
            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, 2) + Mathf.Pow(j - localPos.y, 2) > Mathf.Pow(brushSize, 2))
                        continue;
                    if (i < 0) { if (i < -mWidth / 2) { continue; }}if (i > 0) { if (i > mWidth / 2) { continue; }}if (j < 0) { if (j < -mHeight / 2) { continue; }}if (j > 0) { if (j > mHeight / 2) { continue; } }

                    Color col = MyTex.GetPixel(i + (int)mWidth / 2, j + (int)mHeight / 2);
                    if(col.a ! =0f)
                    {
                        col.a = 0.0 f;
                        colorA++;
                        MyTex.SetPixel(i + (int)mWidth / 2, j + (int)mHeight / 2, col); }}}// Judge the progress as you start scraping
            if(! isStartEraser) { isStartEraser =true;
                InvokeRepeating("getTransparentPercent".0f.0.2 f);
                if(eraserStartEvent ! =null) eraserStartEvent.Invoke(); } MyTex.Apply(); }}double fate;
    /// <summary> 
    ///Check current scratch card progress
    /// </summary>
    /// <returns></returns>
    public void getTransparentPercent()
    {
        if (isEndEraser) { return; }
        fate = colorA / maxColorA * 100;
        fate = (float)Math.Round(fate, 2);
         Debug.Log("Current percentage:" + fate);
        if (fate >= rate)
        {
            isEndEraser = true;
            CancelInvoke("getTransparentPercent");
            uiTex.gameObject.SetActive(false);
            // Trigger the end event
            if(eraserEndEvent ! =null) eraserEndEvent.Invoke(); }}}Copy the code

There are comments in the code, novice words can directly hang, do not need to care about what code interpretation, after all, the true meaning of programming is “CV big method” ha ha ha ha ha ha ~

Code in the use of a Bessel smooth method can be scratch-off when more smooth, will not appear to tear gear and so on!

Then use the mouse after the click distance of the two points, calculate the number of smooth segments and then use Bessel smooth scratch-off effect ~

Finally write a method to complete a scratch-off to judge the progress, when more than a certain proportion of the entire picture!

Attach the script to the Canvas Canvas and drag the RawImage onto the script. RawImage is the image on top of the scratch-off

Use “Image” to display the picture after scraping, and then simply set the size of the brush to control the size of scraping. The effect is as follows:And then… Find two amazing pictures to show off as the top and bottom of the scratch-off


🏳️🌈 Final step: Find two pictures to put in the scene!

This step is said to be the easiest step, but it is also quite difficult!

The hard part is: what kind of images will attract the CSDN elite reading this blog?

I really don’t have any super amazing pictures to show, so just pick two of them

Then click “Image” and “RawImage” in the scene to mount the Image.

As shown below.


🎬 Effect display

Then run Unity for scratch-off! Don’t get addicted to shaving!

Pay attention to the adult anti-addiction mode!

The original drawing is provided!

Scratch-off top picture:Scratch-off below picture:


💬 summary

  • This is the end of the article, mainly wrote a scratch-off case
  • Because from a novice point of view, so each step is a little more said, easy to use and learn
  • If you’re interested in this case or Unity, follow my blog in three waves
  • We will also share more practical and fun case study and small games to learn!
  • If you see here, you can really try to make some small games to play, very easy to get started!
  • Perfect for college students to play games when they are bored in the dorm

🚀 comments section raffle

Now just leave your thoughts on the scratchoff case in the comments section, or mention any other small case you want to learn, I will send out two nuggets MEDALS according to the popularity of the comments (nuggets official bear) ~ in the comments section to share your thoughts!