- 📢博客主頁:https://blog.csdn.net/zhangay1998
- 📢歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請指正!
- 📢本文由 呆呆敲代碼的小Y 原創,首發于 CSDN🙉
- 📢未來很長,值得我們全力奔赴更美好的生活?
- 📢前言
- 🎬只用一個腳本做一個刮刮樂,一不小心刮出來一個女朋友!
- 🏳??🌈第一步:打開Unity,新建一個專案
- 🏳??🌈第二步:新建一個Image圖片和RawImage圖片
- 🏳??🌈第三步:調整相機和畫布的模式
- 🏳??🌈第四步:寫一個腳本,并掛載到Canvas上
- 🏳??🌈最后一步:找兩張圖片放到場景中!
- 🎬效果展示
- 💬總結
- 🚀往期優質文章分享

📢前言
-
前幾天CSDN一個大哥:孤寒者 使用HTML做了一個刮刮樂,大家都挺喜歡看的!
-
我也感覺挺好玩的,那就尋思用 Unity 肯定也能做呀! Unity 是一個容易上手的游戲引擎
-
做出來之后可以直接打包出來給別的 小哥哥小姐姐 直接在手機上玩都行!!
-
那就來簡單說一下怎樣實作這樣一個刮刮樂的小案例吧,只需要一個腳本 就能完成~
-
本文章會從一個新手的角度完整的將全程序都會寫出來!老手直接看腳本掛上即可!
-
如果之前沒接觸過 Unity 也沒關系,這正是你入坑的一個機會!Unity免費學習專欄:🎄 Unity基礎知識學習 🎄
🎬只用一個腳本做一個刮刮樂,一不小心刮出來一個女朋友!

🏳??🌈第一步:打開Unity,新建一個專案
既然我們是用 Unity 完成這個小專案,第一步就來新建一個專案!
如果你連 Unity 引擎是什么都不知道的話,那真的有點落伍啦~
這里推薦一個免費的 Unity 學習專欄,包括 怎樣下載安裝 Unity 和 配置基礎環境 !
以最簡單的一個視角了解 什么是Unity 和 Unity最基礎知識學習!
打開UnityHub新建一個專案,改一下專案名稱和路徑,然后點擊創建,

創建完之后,就會顯示出一個默認的Unity空場景,可能視窗顯示的位置不太一樣,自己可以隨意調整,這個都不重要~

🏳??🌈第二步:新建一個Image圖片和RawImage圖片
在Hierarchy面板上右鍵創建一個Image和一個RawImage
如下圖所示,只需要明白這兩個Image組件都是用來顯示圖片的組件就OK啦~ 想學習更多可以去專欄學習哦!

然后將這兩個Image調整成跟Canvas一個大小!
先點擊Image,選中之后,將圖片調整成Canvas一個大小,按照下圖所示快捷操作即可
也可以手動的將Image圖片調整成跟Canvas一個大小!

Image和RawImage都一樣設定一下,然后場景中變成下面這樣!

🏳??🌈第三步:調整相機和畫布的模式
先選中相機Camera,將相機的投影模式改成 正交,就是改一下這個Projection設定,如下圖所示!

然后再選中Canvas畫布,改成畫布的第二種模式,如下所示:

Canvas畫布概念如下:

然后還沒完,還要將Canvas畫布的縮放模式改為第二種
按照螢屏大小縮放,把解析度調成1920*1080即可!如下所示


🏳??🌈第四步:寫一個腳本,并掛載到Canvas上
上面的幾步都是為了將圖片顯示的時候更加美觀到位 ,這一步才是這個刮刮樂最關鍵的一步!
新建一個C#腳本,然后將以下代碼復制到腳本中即可

直接上代碼
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
{
//是否擦除了
public bool isStartEraser;
//是否擦除結束了
public bool isEndEraser;
//開始事件
public Action eraserStartEvent;
//結束事件
public Action eraserEndEvent;
public RawImage uiTex;
Texture2D tex;
Texture2D MyTex;
int mWidth;
int mHeight;
[Header("筆刷大小")]
public int brushSize = 50;
[Header("刮刮樂比例")]
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>
/// 貝塞爾平滑
/// </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();
}
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 < 1 ? 1 : segments;
if (segments >= 10) { segments = 10; }
Vector2[] points = Beizier(penultPos, lastPos, pos, segments);//進行貝塞爾平滑
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.0f;
colorA++;
MyTex.SetPixel(i + (int)mWidth / 2, j + (int)mHeight / 2, 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 * 100;
fate = (float)Math.Round(fate, 2);
Debug.Log("當前百分比: " + fate);
if (fate >= rate)
{
isEndEraser = true;
CancelInvoke("getTransparentPercent");
uiTex.gameObject.SetActive(false);
//觸發結束事件
if (eraserEndEvent != null)
eraserEndEvent.Invoke();
}
}
}
代碼中有注釋,新手的話直接掛上即可,不需要管什么代碼釋義,畢竟編程的真諦就是“CV大法”哈哈哈哈嗝~
代碼中使用一個貝塞爾平滑的方法可以讓待會刮刮樂的時候更平滑一些,不至于出現撕裂齒輪等等現象!
然后利用滑鼠按下后的兩個點的點擊距離,計算出平滑的段數然后使用貝塞爾平滑進行刮刮樂效果~
最后再寫一個方法,對完成刮刮樂的一個進度來進行判斷,當超過一定比例后顯示整張圖片!
將腳本掛到Canvas畫布上,然后將RawImage拖到這個腳本中,RawImage就是我們刮刮樂上面的那層圖片
刮完之后顯示的圖片用Image,然后簡單設定一下筆刷的大小可以控制刮的時候的大小,效果如下:

然后就是,,找兩張驚艷的圖片用來當做刮刮樂的上層和下層圖片進行展示吧~
🏳??🌈最后一步:找兩張圖片放到場景中!
這一步說是最簡單的一步,其實也挺難的!
難的地方是:要找怎樣的圖片才能吸引到CSDN看到這篇博客的各位精英呢!
我這里實在是沒什么超級驚艷的美圖來展示,那就隨便選兩張吧~
然后點擊場景中的Image 和RawImage ,分別將圖片掛載上去即可!
如下所示


🎬效果展示
然后運行 Unity 進行刮刮樂就好了!千萬不要刮上癮了哦!
注意成年人防沉迷模式!

原圖奉上!
刮刮樂上層圖片:

刮刮樂下層圖片:

💬總結
- 本文到此就結束啦, 主要寫了一個刮刮樂的案例
- 因為是從一個新手角度出發,所以每個步驟都多說了一點,方便使用和學習
- 如果你對這個案例挺感興趣或者對Unity挺感興趣,可以三連一波關注我的博客
- 后面還會分享更多的實用好玩的案例學習和小游戲學習哦!
- 如果你都看到這里了,真的可以自己嘗試一下做一些小游戲玩,上手挺簡單的!
- 非常適合大學生宿舍無聊的時候做小游戲哦~
🚀往期優質文章分享
- ??Unity零基礎到入門 | 游戲引擎 Unity 從0到1的 系統學習 路線【全面總結-建議收藏】!
- 🧡花一天時間做一個高質量飛機大戰游戲,過萬字Unity完整教程!漂亮學妹看了直呼666!
- 💛回憶童年和小伙伴一起玩過的經典游戲【炸彈人小游戲】制作程序+決議
- 💚通宵一晚做出來的一款類似CS的第一人稱射擊游戲Demo!原來做游戲也不是很難
- 🤍爆肝整整一個周末寫一款類似 皇室戰爭 的 即時戰斗類 游戲Demo!兩萬多字游戲制作程序+決議!
- 💙一款類似“恐龍快打”的 橫版街機格斗游戲 該如何制作?| 一起來學習 順便送原始碼【碼文不易,建議收藏學習】
- 💜【超實用技巧】| 提高寫文的質量 和 速率必學技能: Typora 圖床配置 詳細說明
| 🚀 優質專欄分享 🚀 |
- 🎄如果感覺文章看完了不過癮,可以來我的其他 專欄 看一下哦~
- 🎄比如以下幾個專欄:Unity基礎知識學習專欄、Unity游戲制作專欄、Unity實戰類專案 和 演算法學習專欄
- 🎄可以學習更多的關于Unity引擎的相關內容哦!直接點擊下面顏色字體就可以跳轉啦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/297222.html
標籤:其他
上一篇:2021-9-2 Cinemachine 不需要寫代碼的高級跟隨攝像機 2D橫板游戲應用
下一篇:Unity之C#腳本編譯dll
