Unity3D使用GL實現(xiàn)圖案解鎖功能
聊天是時候看到有人問如何在Unity3D的UGUI中實現(xiàn)圖案解鎖的功能,然后便試了一下。剛開始想用LineRender來實現(xiàn),但又一想是要在UGUI中,然后就用了另外一種方法,即使用GL類來實現(xiàn)。
GL相關(guān)介紹及官方文檔
實現(xiàn)后在Android手機上跑的效果如下:
主要實現(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對象,作為連接點。")]
public List<RectTransform> _lstPoints = new List<RectTransform>();
[Tooltip("用于設(shè)置所畫線的顏色。(可使用“unlit/Color”Shader)")]
public Material _matLineColor;
[Tooltip("用于設(shè)置所畫線的高度。")]
public int _nHalfHeight = 15;
[Tooltip("用于設(shè)置選擇時Image的顏色。")]
public Color _clrSelect = Color.red;
[Tooltip("用于設(shè)置未選擇時Image的顏色。")]
public Color _clrUnSelect = Color.white;
[HideInInspector]
public List<RectTransform> _lstSelectPoints = new List<RectTransform>();//已選擇連接點
[HideInInspector]
public List<int> _lstPassword = new List<int>();//以輸入密碼
[HideInInspector]
public Action<bool> onInputState;//true為開始輸入,false為結(jié)束輸入
private bool _isPressing = false;//是否按下
private Vector2 _vtPressPos;//按下點坐標(biāo)
private float _fDistance;//距離
private float _fDegree;//夾角
private Matrix4x4 _matrixTrans;//變換矩陣
private Vector2[] _vertexPos = new Vector2[4];//頂點數(shù)組
private Vector2 _tempPos;
void Awake()
{
InitEnterEvent();//初始化所有連接點的消息
ClearLines();//清空相關(guān)數(shù)據(jù)
}
void Update()
{
if (!IsPressed())
{//當(dāng)未按下時清空是數(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()
{
//為每個點添加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;//進入事件
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);//添加選擇連接點
}
void AddSelectPoint(GameObject obj)
{
if (IsPressed() && null != obj)
{
//將未連接的點添加到需要連接的點的列表中去
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)方向,逆時針為正,順時針為付
if (_tempPos.y < 0)
{
_fDegree *= -1;
}
//設(shè)置變換矩陣
_matrixTrans.SetTRS(vtStart, Quaternion.Euler(0, 0, _fDegree), Vector3.one);//設(shè)置變換矩陣
//設(shè)置繪制頂點坐標(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);
//連接已選擇的點
for (int nIndex = 0; nIndex < _lstSelectPoints.Count - 1; nIndex++)
{
DrawLine(_lstSelectPoints[nIndex].position, _lstSelectPoints[nIndex + 1].position);
}
//連接到Press點
if (IsPressed() && _lstSelectPoints.Count > 0)
{
DrawLine(_vtPressPos, _lstSelectPoints[_lstSelectPoints.Count - 1].position);
}
}
}
上面的實現(xiàn)中都有注明,如有不清楚的地方請留言。繪制主要在DrawLine函數(shù)中。
然后將GraphicUnLockManager類添加到MainCamera上,只有這樣OnPostRender才會被正確調(diào)用,使線能夠在場景中的物體都渲染完成后再繪制。
創(chuàng)建連接點,如下設(shè)置:
設(shè)置GraphicUnLockManager,如下設(shè)置:
接下來就可以在編輯器中運行看看結(jié)果了!按下鼠標(biāo)左鍵開始選擇,釋放結(jié)束選擇,效果如下:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
欄 目:C#教程
下一篇:C#如何從byte[]中直接讀取Structure實例詳解
本文標(biāo)題:Unity3D使用GL實現(xiàn)圖案解鎖功能
本文地址:http://m.jygsgssxh.com/a1/C_jiaocheng/4847.html
您可能感興趣的文章
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新聞效果的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已安裝軟件變化的方法
- 01-10C#實現(xiàn)多線程下載文件的方法
- 01-10C#實現(xiàn)Winform中打開網(wǎng)頁頁面的方法
- 01-10C#實現(xiàn)遠(yuǎn)程關(guān)閉計算機或重啟計算機的方法
- 01-10C#自定義簽名章實現(xiàn)方法
- 01-10C#文件斷點續(xù)傳實現(xiàn)方法
- 01-10winform實現(xiàn)創(chuàng)建最前端窗體的方法


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實例總結(jié)
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-11ajax實現(xiàn)頁面的局部加載


