Unity實現(xiàn)移動端手勢解鎖功能
本文實例為大家分享了Unity實現(xiàn)移動端手勢解鎖的具體代碼,供大家參考,具體內(nèi)容如下
一、效果演示

二、實現(xiàn)思路
——當(dāng)鼠標(biāo)選中一個密碼按鈕時開始記錄輸入的數(shù)字和鼠標(biāo)的起始位置
——當(dāng)鼠標(biāo)按下過程中,始終根據(jù)記錄的鼠標(biāo)起始位置和當(dāng)前鼠標(biāo)的位置兩個點繪制線段并添加到線段的列表中,并一直清空掉列表中除了最后一個線段外的其余線段
——當(dāng)鼠標(biāo)按下過程中,如果有覆蓋到其他的密碼按鈕,則根據(jù)起始的密碼按鈕與當(dāng)前的密碼按鈕兩個點繪制線段并重新記錄輸入的數(shù)字和鼠標(biāo)起始位置
三、實現(xiàn)過程
——創(chuàng)建9個密碼塊,并依次命名為1、2.....9,并設(shè)置tag為PasswordBlock

——編寫生成LineRenderer的方法,初始化LineRenderer屬性的方法,繪制線的方法以及清空線的方法
注意繪制線段時,需要將起始位置和結(jié)束位置的z軸置為0

——編寫記錄密碼和刪除密碼的方法

四、完整代碼(掛載到手勢解鎖界面的物體身上)
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.EventSystems;
public class GestureUnlock : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
{
private List<GameObject> lrList = new List<GameObject>();//存儲每個LineRenderer的列表
private List<GameObject> passwordButtonList = new List<GameObject>();//存儲每個密碼按鈕的列表
private Vector3 startPos;//鼠標(biāo)開始的位置
//線的參數(shù)
public Color startColor = Color.black;//線開始的顏色
public Color endColor = Color.black;//線結(jié)束的顏色
public float width = 0.1f;//線寬度
public int vertices = 90;//頂點數(shù)
public string password;//密碼
private string inputPassword;//輸入的密碼
/// <summary>
/// 刷新線段(拖拽過程中一直刷新)
/// </summary>
private void RefreshLine()
{
if (passwordButtonList.Count == 0)
{
return;
}
LineRenderer uncompleteLR = SpawnLineRenderer(false);
InitLine(uncompleteLR);
DrawLine(uncompleteLR, startPos, ScreenToWorld(Input.mousePosition));
ClearLine(false);
}
/// <summary>
/// 繪制已經(jīng)連線完成的線段
/// </summary>
private void DrawCompleteLine(Vector3 endPos)
{
LineRenderer completeLR = SpawnLineRenderer(true);
InitLine(completeLR);
DrawLine(completeLR, startPos, endPos);
}
/// <summary>
/// 記錄密碼
/// </summary>
/// <param name="_passwordBlock">密碼塊物體</param>
private void RecordPassword(GameObject _passwordButton)
{
passwordButtonList.Add(_passwordButton);
inputPassword += _passwordButton.name;
startPos = _passwordButton.transform.position;//記錄起始位置
}
/// <summary>
/// 刪除密碼
/// </summary>
private void DeletePassword()
{
passwordButtonList.Clear();
inputPassword = "";
}
public void OnBeginDrag(PointerEventData eventData)
{
ClearLine(true);//每次開始拖拽時清空所有線段
GameObject go = eventData.pointerEnter;
if (go != null && go.tag == "PasswordButton" && IsExistInPasswordBlockList(go) == false)
{
RecordPassword(go);//記錄密碼
}
}
public void OnEndDrag(PointerEventData eventData)
{
ClearUnCompleteLine();//清除未完成的線段
}
public void OnDrag(PointerEventData eventData)
{
RefreshLine();//刷新線段(拖拽過程中一直刷新)
GameObject go = eventData.pointerEnter;
if (passwordButtonList.Count != 0 && go != null && go.tag == "PasswordButton" && IsExistInPasswordBlockList(go) == false)
{
DrawCompleteLine(go.transform.position);//繪制已經(jīng)連線完成的線段
RecordPassword(go);//記錄密碼
}
}
#region 線段相關(guān)操作
/// <summary>
/// 生成LineRenderer
/// </summary>
private LineRenderer SpawnLineRenderer(bool isCompleteLine)
{
LineRenderer uncompleteLR = new GameObject().AddComponent<LineRenderer>();
uncompleteLR.material = new Material(Shader.Find("Sprites/Default"));
lrList.Add(uncompleteLR.gameObject);
if (isCompleteLine)
{
uncompleteLR.gameObject.name = "CompleteLine";
}
else
{
uncompleteLR.gameObject.name = "UncompleteLine";
}
return uncompleteLR;
}
/// <summary>
/// 初始化線
/// </summary>
private void InitLine(LineRenderer _uncompleteLR)
{
_uncompleteLR.startColor = startColor;
_uncompleteLR.endColor = endColor;
_uncompleteLR.startWidth = width;
_uncompleteLR.endWidth = width;
_uncompleteLR.numCapVertices = vertices;
_uncompleteLR.numCornerVertices = vertices;
}
/// <summary>
/// 兩點繪制一條直線
/// </summary>
/// <param name="_uncompleteLR">線段</param>
/// <param name="startPos">起始位置</param>
/// <param name="endPos">結(jié)束位置</param>
private void DrawLine(LineRenderer _uncompleteLR, Vector3 startPos, Vector3 endPos)
{
_uncompleteLR.positionCount = 2;
startPos.z = 0;
endPos.z = 0;
_uncompleteLR.SetPosition(0, startPos);
_uncompleteLR.SetPosition(1, endPos);
}
/// <summary>
/// 清除線段
/// </summary>
/// <param name="clearAll">是否清除全部線段</param>
private void ClearLine(bool clearAll)
{
if (lrList.Count == 0)
{
return;
}
for (int i = lrList.Count - 1; i >= 0; i--)
{
GameObject go = lrList[i];
if (clearAll)
{
Destroy(go);
lrList.Remove(go);
}
else
{
if (go.name != "CompleteLine" && i != lrList.Count - 1)
{
Destroy(go);
lrList.Remove(go);
}
}
}
if (clearAll)
{
DeletePassword();
}
}
/// <summary>
/// 清除未完成的線段(每次拖拽結(jié)束時清除)
/// </summary>
private void ClearUnCompleteLine()
{
if (lrList.Count == 0)
{
return;
}
GameObject go = lrList[lrList.Count - 1];
Destroy(go);
lrList.Remove(go);
}
#endregion
#region 工具方法
/// <summary>
/// 當(dāng)前密碼塊是否存在于密碼塊列表中
/// </summary>
/// <param name="_passwordBlock">密碼塊</param>
private bool IsExistInPasswordBlockList(GameObject _passwordButton)
{
if (passwordButtonList.Count == 0)
{
return false;
}
if (passwordButtonList.Contains(_passwordButton))
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 屏幕坐標(biāo)轉(zhuǎn)世界坐標(biāo)
/// </summary>
/// <param name="screenPos">屏幕坐標(biāo)位置</param>
/// <param name="camera">相機</param>
/// <returns>轉(zhuǎn)換后的世界坐標(biāo)</returns>
private Vector3 ScreenToWorld(Vector3 screenPos, Camera camera = null)
{
if (camera == null)
{
camera = Camera.main;
}
Vector3 _screenPos = new Vector3(screenPos.x, screenPos.y, -camera.transform.position.z);
Vector3 v = camera.ScreenToWorldPoint(_screenPos);
return v;
}
#endregion
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于C#操作文件路徑(Directory)的常用靜態(tài)方法詳解
這篇文章主要給大家介紹了關(guān)于C#操作文件路徑(Directory)的常用靜態(tài)方法,Directory類位于System.IO 命名空間,Directory類提供了在目錄和子目錄中進行創(chuàng)建移動和列舉操作的靜態(tài)方法,需要的朋友可以參考下2021-08-08
C# 實現(xiàn)視頻監(jiān)控系統(tǒng)(附源碼)
這篇文章主要介紹了C# 如何實現(xiàn)視頻監(jiān)控系統(tǒng),幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-02-02
C#中實現(xiàn)查找字符串中指定字符位置方法小結(jié)
這篇文章主要為大家介紹了C#中實現(xiàn)查找字符串中指定字符位置的常用方法,本文將以"."字符為例,詳細講解這些方法的具體使用,需要的可以參考下2024-02-02
C#集合Collections購物車Shopping Cart(實例講解)
下面小編就為大家分享一篇C#集合Collections購物車Shopping Cart的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12

