Unity3D使用GL實(shí)現(xiàn)圖案解鎖功能
聊天是時(shí)候看到有人問如何在Unity3D的UGUI中實(shí)現(xiàn)圖案解鎖的功能,然后便試了一下。剛開始想用LineRender來實(shí)現(xiàn),但又一想是要在UGUI中,然后就用了另外一種方法,即使用GL類來實(shí)現(xiàn)。
GL相關(guān)介紹及官方文檔
實(shí)現(xiàn)后在Android手機(jī)上跑的效果如下:
主要實(shí)現(xiàn)GraphicUnLockManager類。代碼如下:
using UnityEngine; using System.Collections.Generic; using System; using UnityEngine.EventSystems; using UnityEngine.UI; public class GraphicUnLockManager : MonoBehaviour { [Tooltip("含有Selectable及Image組件的UI對象,作為連接點(diǎn)。")] public List<RectTransform> _lstPoints = new List<RectTransform>(); [Tooltip("用于設(shè)置所畫線的顏色。(可使用“unlit/Color”Shader)")] public Material _matLineColor; [Tooltip("用于設(shè)置所畫線的高度。")] public int _nHalfHeight = 15; [Tooltip("用于設(shè)置選擇時(shí)Image的顏色。")] public Color _clrSelect = Color.red; [Tooltip("用于設(shè)置未選擇時(shí)Image的顏色。")] public Color _clrUnSelect = Color.white; [HideInInspector] public List<RectTransform> _lstSelectPoints = new List<RectTransform>();//已選擇連接點(diǎn) [HideInInspector] public List<int> _lstPassword = new List<int>();//以輸入密碼 [HideInInspector] public Action<bool> onInputState;//true為開始輸入,false為結(jié)束輸入 private bool _isPressing = false;//是否按下 private Vector2 _vtPressPos;//按下點(diǎn)坐標(biāo) private float _fDistance;//距離 private float _fDegree;//夾角 private Matrix4x4 _matrixTrans;//變換矩陣 private Vector2[] _vertexPos = new Vector2[4];//頂點(diǎn)數(shù)組 private Vector2 _tempPos; void Awake() { InitEnterEvent();//初始化所有連接點(diǎn)的消息 ClearLines();//清空相關(guān)數(shù)據(jù) } void Update() { if (!IsPressed()) {//當(dāng)未按下時(shí)清空是數(shù)據(jù) ClearLines(); } } bool IsPressed() { //觸摸 if (Input.touchCount > 0) { switch (Input.touches[0].phase) { case TouchPhase.Began: _isPressing = true; if (onInputState != null) { onInputState(true);//狀態(tài)改變 } break; case TouchPhase.Ended: case TouchPhase.Canceled: _isPressing = false; if (onInputState != null) { onInputState(false);//狀態(tài)改變 } break; } _vtPressPos = Input.touches[0].position; } else { //鼠標(biāo) if (Input.GetMouseButtonDown(0)) { _isPressing = true; if (onInputState != null) { onInputState(true);//狀態(tài)改變 } } if (Input.GetMouseButtonUp(0)) { _isPressing = false; if (onInputState != null) { onInputState(false);//狀態(tài)改變 } } _vtPressPos = Input.mousePosition; } return _isPressing; } void OnPostRender() { DrawLines();//畫所有線 } void OnGUI() { string msg = ""; msg += "是否正在輸入:" + IsPressed() + "\n"; msg += "密碼:"; for (int i = 0; i < _lstPassword.Count; i++) { msg += _lstPassword[i] + ","; } GUIStyle guiStyle = new GUIStyle(); guiStyle.normal.textColor = new Color(1, 1, 1); //設(shè)置字體顏色 guiStyle.fontSize = 75; //設(shè)置字體大小 GUILayout.Label(msg, guiStyle); } void InitEnterEvent() { //為每個(gè)點(diǎn)添加Enter事件 _lstPoints.ForEach((rtTrans) => { EventTrigger trigger = rtTrans.GetComponent<EventTrigger>(); if (trigger == null) { trigger = rtTrans.gameObject.AddComponent<EventTrigger>(); } //添加事件 EventTrigger.Entry entryEnter = new EventTrigger.Entry(); entryEnter.eventID = EventTriggerType.PointerEnter;//進(jìn)入事件 EventTrigger.TriggerEvent evtEnter = new EventTrigger.TriggerEvent(); evtEnter.AddListener(OnSelectPoint); entryEnter.callback = evtEnter; trigger.triggers.Add(entryEnter); EventTrigger.Entry entryDown= new EventTrigger.Entry(); entryDown.eventID = EventTriggerType.PointerDown;//按下事件 EventTrigger.TriggerEvent evtDown = new EventTrigger.TriggerEvent(); evtDown.AddListener(OnSelectPoint); entryDown.callback = evtDown; trigger.triggers.Add(entryDown); }); } public void OnSelectPoint(BaseEventData obj) { //轉(zhuǎn)換數(shù)據(jù)類型 PointerEventData data = obj as PointerEventData; GameObject target = null; if (null != data.pointerEnter) { target = data.pointerEnter; } else if (null != data.pointerPress) { target = data.pointerPress; } AddSelectPoint(target);//添加選擇連接點(diǎn) } void AddSelectPoint(GameObject obj) { if (IsPressed() && null != obj) { //將未連接的點(diǎn)添加到需要連接的點(diǎn)的列表中去 RectTransform rtTrans = obj.GetComponent<RectTransform>(); if (null != rtTrans && !_lstSelectPoints.Contains(rtTrans)) { //添加到繪制列表 _lstSelectPoints.Add(rtTrans); //添加密碼序列 _lstPassword.Add(_lstPoints.IndexOf(rtTrans)); //改變顏色 rtTrans.GetComponent<Image>().color = _clrSelect; } } } void ClearLines() { //清空選擇及密碼列表 _lstSelectPoints.Clear(); _lstPassword.Clear(); //還原顏色 _lstPoints.ForEach((rtTrans) => { rtTrans.GetComponent<Image>().color = _clrUnSelect; }); } void DrawLine(Vector2 vtStart, Vector2 vtEnd) { _tempPos = vtEnd - vtStart; _fDistance = Vector3.Distance(Vector3.zero, _tempPos);//距離 _fDegree = Vector3.Angle(_tempPos, Vector3.right);//與x軸正方向的夾角 //判斷旋轉(zhuǎn)方向,逆時(shí)針為正,順時(shí)針為付 if (_tempPos.y < 0) { _fDegree *= -1; } //設(shè)置變換矩陣 _matrixTrans.SetTRS(vtStart, Quaternion.Euler(0, 0, _fDegree), Vector3.one);//設(shè)置變換矩陣 //設(shè)置繪制頂點(diǎn)坐標(biāo) _vertexPos[0].x = 0; _vertexPos[0].y = -_nHalfHeight; _vertexPos[1].x = 0; _vertexPos[1].y = _nHalfHeight; _vertexPos[2].x = _fDistance; _vertexPos[2].y = _nHalfHeight; _vertexPos[3].x = _fDistance; _vertexPos[3].y = -_nHalfHeight; //繪制 GL.PushMatrix(); GL.LoadPixelMatrix();//使(0,0,0)為左下角,(Screen.width,Screen.height,0)為右上角 GL.MultMatrix(_matrixTrans); GL.Begin(GL.QUADS);//繪制四邊形 for (int n = 0; n < 4; n++) { GL.Vertex(_vertexPos[n]); } GL.End(); GL.PopMatrix(); } void DrawLines() { //設(shè)置線的材質(zhì) _matLineColor.SetPass(0); //連接已選擇的點(diǎn) for (int nIndex = 0; nIndex < _lstSelectPoints.Count - 1; nIndex++) { DrawLine(_lstSelectPoints[nIndex].position, _lstSelectPoints[nIndex + 1].position); } //連接到Press點(diǎn) if (IsPressed() && _lstSelectPoints.Count > 0) { DrawLine(_vtPressPos, _lstSelectPoints[_lstSelectPoints.Count - 1].position); } } }
上面的實(shí)現(xiàn)中都有注明,如有不清楚的地方請留言。繪制主要在DrawLine函數(shù)中。
然后將GraphicUnLockManager類添加到MainCamera上,只有這樣OnPostRender才會被正確調(diào)用,使線能夠在場景中的物體都渲染完成后再繪制。
創(chuàng)建連接點(diǎn),如下設(shè)置:
設(shè)置GraphicUnLockManager,如下設(shè)置:
接下來就可以在編輯器中運(yùn)行看看結(jié)果了!按下鼠標(biāo)左鍵開始選擇,釋放結(jié)束選擇,效果如下:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
深入C#中使用SqlDbType.Xml類型參數(shù)的使用詳解
本篇文章是對在C#中使用SqlDbType.Xml類型參數(shù)的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05unity實(shí)現(xiàn)場景切換進(jìn)度條顯示
這篇文章主要為大家詳細(xì)介紹了unity實(shí)現(xiàn)場景切換進(jìn)度條顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11如何應(yīng)用C#實(shí)現(xiàn)UDP的分包組包
本篇文章小編將為大家介紹,如何應(yīng)用C#實(shí)現(xiàn)UDP的分包組包。需要的朋友參考下2013-04-04C#連接SQL?Sever數(shù)據(jù)庫與數(shù)據(jù)查詢實(shí)例之?dāng)?shù)據(jù)倉庫詳解
最近的工作遇到了連接查詢,特在此記錄,以免日后以往,下面這篇文章主要給大家介紹了關(guān)于C#連接SQL?Sever數(shù)據(jù)庫與數(shù)據(jù)查詢實(shí)例之?dāng)?shù)據(jù)倉庫的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06在C#中使用OpenCV(使用OpenCVSharp)的實(shí)現(xiàn)
這篇文章主要介紹了在C#中使用OpenCV(使用OpenCVSharp)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11