unity教程:unity实现输入手势检测
尘风一枚
2023年12月16日 22:22

//尘风

using System;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.EventSystems;

using UnityEngine.UI;

public class ui_thread : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerEnterHandler, IEndDragHandler

{

public Canvas canvas;

public RectTransform fingerLine;

//已选择的连线

public List<sta> games = new List<sta>();

//手势密码

public List<(string[], Action)> ss = new List<(string[], Action)>();

//测试起点位置

public RectTransform start;

public Text text;

//手指或鼠标在屏幕上的点击位置

private Vector3 touchPos;

private bool isPress = false;

private void Start()

{

string[] vs1 = { "1", "2", "3", "5", "7", "8", "9" };

ss.Add((vs1, cs1));

string[] vs2 = { "7", "4", "1", "5", "9", "6", "3" };

ss.Add((vs2, cs2));

}

public void cs1()

{

text.text = "手势正确-Z";

}

public void cs2()

{

text.text = "手势正确-N";

}

//针对手指位置和对应UI控件之间的连线需要转换坐标处理

private void UpdateFingerLine(Vector3 startPos)

{

Vector3 uiStartPos = Vector3.zero;

Vector3 uitouchPos = Vector3.zero;

if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)

{

uiStartPos = startPos;

uitouchPos = touchPos;

}

else if (canvas.renderMode == RenderMode.ScreenSpaceCamera)

{

Camera camera = canvas.worldCamera;

//UI世界的起点世界坐标转换为UGUI坐标

Vector2 screenStartPos = RectTransformUtility.WorldToScreenPoint(camera, startPos);

RectTransformUtility.ScreenPointToWorldPointInRectangle(canvas.GetComponent<RectTransform>(), screenStartPos,

camera, out uiStartPos);

//鼠标坐标转换为UGUI坐标

RectTransformUtility.ScreenPointToWorldPointInRectangle(canvas.GetComponent<RectTransform>(), touchPos,

camera, out uitouchPos);

}

fingerLine.pivot = new Vector2(0, 0.5f);

fingerLine.position = startPos;

fingerLine.eulerAngles = new Vector3(0, 0, GetAngle(uiStartPos, uitouchPos));

fingerLine.sizeDelta = new Vector2(GetDistance(uiStartPos, uitouchPos), fingerLine.sizeDelta.y);

}

//通用设置线的,如果只设置两点之间连线,只需要初入对应的ui控件的Position

//针对手指位置和对应UI控件之间的连线需要转换坐标处理

private RectTransform SetLine(RectTransform lineSource, Vector3 startPos, Vector3 endPos)

{

RectTransform line = lineSource;//Instantiate(lineSource, lineSource.parent);

line.pivot = new Vector2(0, 0.5f);

line.position = startPos;

line.eulerAngles = new Vector3(0, 0, GetAngle(startPos, endPos));

line.sizeDelta = new Vector2(GetDistance(startPos, endPos), lineSource.sizeDelta.y);

return line;

}

private float GetAngle(Vector3 startPos, Vector3 endPos)

{

Vector3 dir = endPos - startPos;

float angle = Vector3.Angle(Vector3.right, dir);

Vector3 cross = Vector3.Cross(Vector3.right, dir);

float dirF = cross.z > 0 ? 1 : -1;

angle = angle * dirF;

return angle;

}

private float GetDistance(Vector3 startPos, Vector3 endPos)

{

float distance = Vector3.Distance(endPos, startPos);

return distance * 1 / canvas.transform.localScale.x;

}

public void OnPointerDown(PointerEventData eventData)

{

if(eventData.pointerEnter != null && eventData.pointerEnter.GetComponent<sta>() != null)

{

start = (RectTransform)eventData.pointerEnter.transform;

}

}

public void OnDrag(PointerEventData eventData)

{

if (start != null)

{

if (Application.isMobilePlatform)

{

for (int i = 0; i < Input.touchCount; ++i)

{

UnityEngine.Touch touch = Input.GetTouch(i);

if (touch.phase == TouchPhase.Began)

{

isPress = true;

touchPos = touch.position;

}

else

{

isPress = false;

}

}

}

else

{

if (Input.GetMouseButton(0))

{

isPress = true;

touchPos = Input.mousePosition;

}

else

{

isPress = false;

}

}

}

if (isPress)

{

fingerLine.gameObject.SetActive(true);

UpdateFingerLine(start.position);

}

else

{

fingerLine.gameObject.SetActive(false);

}

if (eventData.pointerEnter != null && eventData.pointerEnter.GetComponent<sta>() != null)

{

if (eventData.pointerEnter.name != start.name)

{

bool cs = true;

for (int i = 0; i < games.Count; i++)

{

if(games[i].name == eventData.pointerEnter.name+"cs")

{

cs = false;

}

}

if (cs)

{

GameObject game = Instantiate(fingerLine.gameObject, start.position, Quaternion.identity, fingerLine.parent);

game.name = start.gameObject.name + "cs";

game.AddComponent<sta>();

game.GetComponent<sta>().id = start.GetComponent<sta>().id;

SetLine((RectTransform)game.transform, start.position, eventData.pointerEnter.transform.position);

games.Add(game.GetComponent<sta>());

start = (RectTransform)eventData.pointerEnter.transform;

}

}

}

}

public void OnPointerEnter(PointerEventData eventData)

{

//泥嚎

}

public void OnEndDrag(PointerEventData eventData)

{

games.Add(start.GetComponent<sta>());

jcGame();

while (games.Count > 0)

{

if (games.Count == 1)

{

games.Clear();

}

else

{

Destroy(games[0].gameObject);

games.RemoveAt(0);

}

}

start = null;

fingerLine.gameObject.SetActive(false);

}

public void jcGame()

{

for (int i = 0; i < ss.Count; i++)

{

(string[] vs, Action ac) = ss[i];

if (vs.Length == games.Count)

{

bool cs = true;

for (int j = 0; j < games.Count; j++)

{

if (games[j].id != vs[j])

{

cs = false;

}

}

if (cs)

{

ac.Invoke();

}

}

else

{

text.text = "手势错误";

}

}

}

}