服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - Unity3D使用GL实现图案解锁功能

Unity3D使用GL实现图案解锁功能

2022-07-08 09:35星空不语 C#

这篇文章主要为大家详细介绍了Unity3D使用GL实现图案解锁功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

聊天是时候看到有人问如何在Unity3D的UGUI中实现图案解锁的功能,然后便试了一下。刚开始想用LineRender来实现,但又一想是要在UGUI中,然后就用了另外一种方法,即使用GL类来实现。

GL相关介绍及官方文档

实现后在Android手机上跑的效果如下:

Unity3D使用GL实现图案解锁功能

主要实现GraphicUnLockManager类。代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
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("用于设置所画线的颜色。(可使用“unlit/Color”Shader)")]
 public Material _matLineColor;
 [Tooltip("用于设置所画线的高度。")]
 public int _nHalfHeight = 15;
 [Tooltip("用于设置选择时Image的颜色。")]
 public Color _clrSelect = Color.red;
 [Tooltip("用于设置未选择时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为结束输入
 
 private bool _isPressing = false;//是否按下
 private Vector2 _vtPressPos;//按下点坐标
 
 private float _fDistance;//距离
 private float _fDegree;//夹角
 private Matrix4x4 _matrixTrans;//变换矩阵
 private Vector2[] _vertexPos = new Vector2[4];//顶点数组
 
 private Vector2 _tempPos;
 
 void Awake()
 {
  InitEnterEvent();//初始化所有连接点的消息
  ClearLines();//清空相关数据
 }
 
 void Update()
 {
  if (!IsPressed())
  {//当未按下时清空是数据
   ClearLines();
  }
 }
 
 bool IsPressed()
 {
  //触摸
  if (Input.touchCount > 0)
  {
   switch (Input.touches[0].phase)
   {
    case TouchPhase.Began:
     _isPressing = true;
     if (onInputState != null)
     {
      onInputState(true);//状态改变
     }
     break;
    case TouchPhase.Ended:
    case TouchPhase.Canceled:
     _isPressing = false;
     if (onInputState != null)
     {
      onInputState(false);//状态改变
     }
     break;
   }
 
   _vtPressPos = Input.touches[0].position;
  }
  else
  {
   //鼠标
   if (Input.GetMouseButtonDown(0))
   {
    _isPressing = true;
    if (onInputState != null)
    {
     onInputState(true);//状态改变
    }
   }
   if (Input.GetMouseButtonUp(0))
   {
    _isPressing = false;
    if (onInputState != null)
    {
     onInputState(false);//状态改变
    }
   }
 
   _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); //设置字体颜色
  guiStyle.fontSize = 75;  //设置字体大小
  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)
 {
  //转换数据类型
  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轴正方向的夹角
 
  //判断旋转方向,逆时针为正,顺时针为付
  if (_tempPos.y < 0)
  {
   _fDegree *= -1;
  }
 
  //设置变换矩阵
  _matrixTrans.SetTRS(vtStart, Quaternion.Euler(0, 0, _fDegree), Vector3.one);//设置变换矩阵
 
 
  //设置绘制顶点坐标
  _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()
 {
  //设置线的材质
  _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);
  }
 }
}

上面的实现中都有注明,如有不清楚的地方请留言。绘制主要在DrawLine函数中。

然后将GraphicUnLockManager类添加到MainCamera上,只有这样OnPostRender才会被正确调用,使线能够在场景中的物体都渲染完成后再绘制。

创建连接点,如下设置:

Unity3D使用GL实现图案解锁功能

设置GraphicUnLockManager,如下设置:

Unity3D使用GL实现图案解锁功能

接下来就可以在编辑器中运行看看结果了!按下鼠标左键开始选择,释放结束选择,效果如下:

Unity3D使用GL实现图案解锁功能

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/u012741077/article/details/52551181

延伸 · 阅读

精彩推荐
  • C#C#实现将浮点数表示的货币数量以汉字大写形式输出的方法

    C#实现将浮点数表示的货币数量以汉字大写形式输出的方法

    这篇文章主要介绍了C#实现将浮点数表示的货币数量以汉字大写形式输出的方法,涉及C#针对浮点数的遍历与字符替换操作技巧,具有一定参考借鉴价值,需要的...

    北风其凉3822021-10-11
  • C#C#线程处理系列之线程池中的I/O线程

    C#线程处理系列之线程池中的I/O线程

    这篇文章主要介绍了C#线程处理系列之线程池中的I/O线程,在这篇文章中将介绍如何用线程池中的I/O线程来执行I/O操作,感兴趣的小伙伴们可以参考一下...

    Learning hard10442021-11-17
  • C#C#调用webservice接口的最新方法教程

    C#调用webservice接口的最新方法教程

    webservice 可以用于分布式应用程序之间的交互,和不同程序之间的交互。下面这篇文章主要给大家介绍了关于C#调用webservice接口的相关资料,文中通过图文...

    上青天揽月4032022-02-10
  • C#基于C#的抽象类别详解

    基于C#的抽象类别详解

    下面小编就为大家分享一篇基于C#的抽象类别详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    Insus.NET9852022-02-17
  • C#Windows下C#的GUI窗口程序中实现调用Google Map的实例

    Windows下C#的GUI窗口程序中实现调用Google Map的实例

    这篇文章主要介绍了Windows下C#的GUI窗口程序中实现调用Google Map的实例,如果只想调用浏览器打开网页的话可以看文章最后的方法,需要的朋友可以参考下...

    hzy37745782021-11-18
  • C#C#实现JSON解析器MojoUnityJson功能(简单且高效)

    C#实现JSON解析器MojoUnityJson功能(简单且高效)

    MojoUnityJson 是使用C#实现的JSON解析器 ,算法思路来自于游戏引擎Mojoc的C语言实现 Json.h。这篇文章主要介绍了C#实现JSON解析器MojoUnityJson的方法,需要的朋友...

    scottcgi11712022-02-19
  • C#C#中重载重写和覆盖的定义与区别

    C#中重载重写和覆盖的定义与区别

    今天小编就为大家分享一篇关于C#中重载重写和覆盖的定义与区别,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随...

    Czhenya3592022-03-03
  • C#基于C#动手实现网络服务器Web Server

    基于C#动手实现网络服务器Web Server

    这篇文章主要为大家详细介绍了基于C#动手实现网络服务器Web Server,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Deali-Axy5392022-01-25