1. 程式人生 > 程式設計 >Unity實現移動端手勢解鎖功能

Unity實現移動端手勢解鎖功能

本文例項為大家分享了Unity實現移動端手勢解鎖的具體程式碼,供大家參考,具體內容如下

一、效果演示

Unity實現移動端手勢解鎖功能

二、實現思路

——當滑鼠選中一個密碼按鈕時開始記錄輸入的數字和滑鼠的起始位置
——當滑鼠按下過程中,始終根據記錄的滑鼠起始位置和當前滑鼠的位置兩個點繪製線段並新增到線段的列表中,並一直清空掉列表中除了最後一個線段外的其餘線段
——當滑鼠按下過程中,如果有覆蓋到其他的密碼按鈕,則根據起始的密碼按鈕與當前的密碼按鈕兩個點繪製線段並重新記錄輸入的數字和滑鼠起始位置

三、實現過程

——建立9個密碼塊,並依次命名為1、2.....9,並設定tag為PasswordBlock

Unity實現移動端手勢解鎖功能

——編寫生成LineRenderer的方法,初始化LineRenderer屬性的方法,繪製線的方法以及清空線的方法

注意繪製線段時,需要將起始位置和結束位置的z軸置為0

Unity實現移動端手勢解鎖功能

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

Unity實現移動端手勢解鎖功能

四、完整程式碼(掛載到手勢解鎖介面的物體身上)

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;//滑鼠開始的位置
 
 //線的引數
 public Color startColor = Color.black;//線開始的顏色
 public Color endColor = Color.black;//線結束的顏色
 public float width = 0.1f;//線寬度
 public int vertices = 90;//頂點數
 
 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>
 /// 繪製已經連線完成的線段
 /// </summary>
 private void DrawCompleteLine(Vector3 endPos)
 {
 LineRenderer completeLR = SpawnLineRenderer(true);
 InitLine(completeLR);
 DrawLine(completeLR,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);//繪製已經連線完成的線段
 
 RecordPassword(go);//記錄密碼
 }
 }
 
 #region 線段相關操作
 
 /// <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">結束位置</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>
 /// 清除未完成的線段(每次拖拽結束時清除)
 /// </summary>
 private void ClearUnCompleteLine()
 {
 if (lrList.Count == 0)
 {
 return;
 }
 
 GameObject go = lrList[lrList.Count - 1];
 Destroy(go);
 lrList.Remove(go);
 }
 
 #endregion
 
 #region 工具方法
 
 /// <summary>
 /// 當前密碼塊是否存在於密碼塊列表中
 /// </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>
 /// 螢幕座標轉世界座標
 /// </summary>
 /// <param name="screenPos">螢幕座標位置</param>
 /// <param name="camera">相機</param>
 /// <returns>轉換後的世界座標</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
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。