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

 更新时间:2020年6月25日 10:37  点击:2464

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

GL相关介绍及官方文档

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

主要实现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("用于设置所画线的颜色。(可使用“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才会被正确调用,使线能够在场景中的物体都渲染完成后再绘制。

创建连接点,如下设置:

设置GraphicUnLockManager,如下设置:

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

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

[!--infotagslink--]

相关文章

  • Unity3D UGUI实现翻书特效

    这篇文章主要为大家详细介绍了Unity3D UGUI实现翻书特效,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D使用GL实现图案解锁功能

    这篇文章主要为大家详细介绍了Unity3D使用GL实现图案解锁功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现飞机大战游戏(1)

    这篇文章主要为大家详细介绍了Unity3D实现飞机大战游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-11-03
  • Unity3D游戏开发数据持久化PlayerPrefs的用法详解

    在本篇文章里小编给大家整理了关于Unity3D游戏开发之数据持久化PlayerPrefs的使用的相关知识点内容,需要的朋友们参考下。...2020-06-25
  • Unity3D基于OnGUI实时显示FPS

    这篇文章主要介绍了Unity3D基于OnGUI实时显示FPS,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D仿写Button面板事件绑定功能

    这篇文章主要为大家详细介绍了Unity3D仿写Button面板事件绑定功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • unity3D实现三维物体跟随鼠标

    这篇文章主要为大家详细介绍了unity3D实现三维物体跟随鼠标,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • unity3d调用手机或电脑摄像头

    这个是在网上看到的,经测试可以在电脑上运行,确实调用了本地摄像头。有需要的小伙伴可以参考下。...2020-06-25
  • Unity3D Shader实现镜子效果

    这篇文章主要为大家详细介绍了Unity3D Shader实现镜子效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现待机状态图片循环淡入淡出

    这篇文章主要为大家详细介绍了Unity3D实现待机状态图片循环淡入淡出,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D Shader实现动态屏幕遮罩

    这篇文章主要为大家详细介绍了Unity3D Shader实现动态屏幕遮罩效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D使用UGUI开发原生虚拟摇杆

    这篇文章主要为大家详细介绍了Unity3D使用UGUI开发原生虚拟摇杆,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D UGUI特效之Image高斯模糊效果

    这篇文章主要为大家详细介绍了Unity3D UGUI特效之Image高斯模糊效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现物体闪烁效果

    这篇文章主要为大家详细介绍了Unity3D实现物体闪烁效果,类似霓虹灯、跑马灯、LED灯效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • 混合语言编程—C#使用原生的Directx和OpenGL绘图的方法

    本文要说的是混合C#和C/C++语言编程,在C#的Winform和WPF下使用原生的Direct和OpenGL进行绘图...2020-06-25
  • Unity3D利用DoTween实现卡牌翻转效果

    这篇文章主要为大家详细介绍了Unity3D利用DoTween实现卡牌翻转效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现分页系统

    这篇文章主要为大家详细介绍了Unity3D实现分页系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D实现鼠标控制视角转动

    这篇文章主要为大家详细介绍了Unity3D实现鼠标控制视角转动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity3D生成一段隧道网格的方法

    这篇文章主要为大家详细介绍了Unity3D生成一段隧道网格的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-18
  • Unity3d获取系统时间

    本文通过一段代码给大家详解unity3d获取系统时间,代码简单易懂,小伙伴们快来看看吧...2020-06-25