用Unity做一个简单的手势解锁

来源:互联网 发布:黄牛党抢票软件 编辑:程序博客网 时间:2024/05/16 01:59

最近有机会用Unity做了一个简单的手势解锁,工具:Unity5.4,语言:C#


界面及实现方法相当low,只是作为交流,请各位大虾轻喷,且我做的这个有一个坑后面会交代。

最开始做的时候,大概思路是,把手势解锁分为三块来做:

一是搭建界面;

二是实现手势划线逻辑;

三是实现解锁的各种逻辑,比如密码创建、储存、修改、删除,手势的创建、判断、储存、手指中途离开屏幕的处理、经过点自定连线的手势处理等等。

我在这里主要记录手势划线逻辑的处理,因为最开始做之前在网上搜索实现方法,都不是很理想,做过的实现的方法和我想要的不太一样,所以干脆花上点时间来做一个,且Unity贵为一款3D游戏引擎来做“手势解锁”,似乎也难倒了我这个大汉,大虾看到此别怪我,我交代我是菜鸟。如果想在这篇文章上看到完整的解锁代码,请出门左转吧。

----------------------------------------------------------分割线·先占个坑以后再更-------------------------------------------------------------

我的想法:要实现手势滑动,就得先实现用鼠标(编辑器模式下用鼠标代替手指)划一条线处理,且点击第一下画出线的第一个点,然后按照鼠标左键拖拽实现划线,即线的第二个点要跟随触碰点移动。能顺利画下第一条线后就加入“经过手势点相关逻辑,比如存储该点代表的密码,并将该点设置为下一条线的起点等等逻辑”,然后画第二条线,第三条,第四条、、、、、

那么问题来了,如何实现划线?Unity中并没有“线”这个组件,我是使用UGUI中的Image组件,添加一个Image,将它做成一个小长方块(不要做得太宽,因为你的线本就很细),然后在运行时动态改变其位置position、角度rotation、尺寸size,线预设如下图:


线是这样画出来的:创建一个脚本,让脚本继承IBeginDragHandler, IDragHandler, IEndDragHandler这几个接口,并实现接口的三个方法:

拖拽前处理: public void OnBeginDrag(PointerEventData eventData){  }

拖拽中处理: public void OnDrag(PointerEventData eventData){  }

拖拽后处理: public void OnEndDrag(PointerEventData eventData){  }

备注:继承接口,必须实现接口的全部方法,如果接口方法中这次不会被使用,仍然要实现该方法,但是不用覆写里面的具体代码(弄一个空方法就可以),比如OnEndDrag就里面就可以写个空的。

以下是实现划线的代码:

using UnityEngine;using UnityEngine.UI;using System.Collections;using System.Collections.Generic;using System.Text;using UnityEngine.EventSystems;                                                 //Unity事件系统命名空间public class Test : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{    public GameObject GoLinePrefab;                                             //线预设    public static GameObject Line;                                              //线对象    public RectTransform LineRectTranform;                                      //二维方位    public static Vector3 firstPosition;                                        //起点位置    public static Vector3 secondPosition;                                       //终点位置    public GameObject GoButtonPanel;                                            //按钮面板    void Start()    {        //加载Line        GameObject goLine = GameObject.Instantiate(GoLinePrefab) as GameObject;        Line = goLine;        //设置其父对象        goLine.transform.parent = GoButtonPanel.transform;    }    /// <summary>    /// 拖拽前处理    /// </summary>    /// <param name="eventData"></param>    public void OnBeginDrag(PointerEventData eventData)    {        /* 设置线的第一个点位置 */        Vector3 globalMousePosition;                                            //转换后的鼠标的位置        //屏幕坐标,转二维矩阵坐标        if (RectTransformUtility.ScreenPointToWorldPointInRectangle(LineRectTranform, eventData.position, eventData.pressEventCamera, out globalMousePosition))        {            firstPosition = globalMousePosition;                                //将鼠标位置赋值给第一个点        }    }    /// <summary>    /// 拖拽中处理    /// </summary>    /// <param name="eventData"></param>    public void OnDrag(PointerEventData eventData)    {        Vector3 globalMousePosition;                                            //转换后的鼠标的位置        //屏幕坐标,转二维矩阵坐标        if (RectTransformUtility.ScreenPointToWorldPointInRectangle(LineRectTranform, eventData.position, eventData.pressEventCamera, out globalMousePosition))        {            if (PasswordHandle.IsEnterArea == false)            {                secondPosition = globalMousePosition;                           //拖拽时,实时的将鼠标位置赋值给第二个点            }            if (Line != null)            {                //设置position                Line.transform.position = (firstPosition + secondPosition) / 2;//**向量的中点坐标公式,不要说你忘了                //设置rotation                Vector3 vecRotation = (secondPosition - firstPosition);        //**向量减法来求方向                Line.transform.eulerAngles = new Vector3(0, 0, Mathf.Atan2(vecRotation.y, vecRotation.x) * Mathf.Rad2Deg);//**这里使用了反三角函数,中学知识                //设置scale                Line.transform.localScale = new Vector3(Mathf.Sqrt(Vector3.Dot(vecRotation, vecRotation)) / 100, 1, 1);                //Vector3.Dot(vecRotation, vecRotation)点乘,此处相当于求vecRotation向量的模,即长度                //这里“/100”是一个坑,调了好久才调出来,除以多少和屏幕尺寸有关,这样线的第二个点才会紧跟着鼠标移动,整条线不会脱离鼠标(比实际画的短或长)                //我设置的屏幕尺寸是600*800.,其他尺寸自己调吧            }        }    }    /// <summary>    /// 拖拽后处理    /// </summary>    /// <param name="eventData"></param>    public void OnEndDrag(PointerEventData eventData)    {    }}
代码码好后,在UnIty中搭建一个测试场景,建一个Canvas,在其下建一个Panel,把上面写的“Test.cs”脚本挂到Panel上,把提前做好的线预设(我取得名字叫“Line”)拖到Canvas下面,对 GoLinePrefab线预设,LineRectTranform线二维方位(和线预设是同一个对象),GoButtonPanel按钮面板进行拖拽赋值。


并把Panel的锚点Anchor设置为左下角(这样UI的坐标左下角才是原点,才能和屏幕世界坐标系保持一致),如图:


最后设置好屏幕尺寸:600*800,就可以测试进行划线了。

    

能画出第一条线,那么在手势解锁界面,只需要将手势点作为线的第一个点,线的第二个点的位置(在鼠标未碰到下一个手势点前)则为鼠标的实时位置,碰到下一个手势点时,将该点设置为线的第二点,两点连成一条线,然后用Instantiate创建下一条线继续画,然后添加判断逻辑、中间点自动连线逻辑等等,就实现了一个完整的手势解锁。

我实现这个功能有一个坑,就是只有在屏幕尺寸为600*800时,求出第一个点与第二个点的长度除以100得出的商值,并将此值赋值给线的Size,线的尺寸才能完美的匹配鼠标的轨迹,,,,,所以希望大神能给出更好的方法,评论区可以交流交流。

1 0
原创粉丝点击