Skip to content

Instantly share code, notes, and snippets.

@dyzsunson
Forked from boj/GestureTracker.cs
Created December 20, 2016 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dyzsunson/a52ae754d791202264e495f55eb717cd to your computer and use it in GitHub Desktop.
Save dyzsunson/a52ae754d791202264e495f55eb717cd to your computer and use it in GitHub Desktop.
Unity3d Touch Tracking
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/**
Spits out a string based on gesture directions regardless of size or location.
Example:
TOP LEFT -> BOTTOM RIGHT SLASH = 13
TOP RIGHT -> BOTTOM LEFT SLASH = 32
COUNTER CLOCKWISE CIRCLE FROM TOP = 23142
CLOCKWISE CIRCLE FROM TOP = 13241
*/
public class GestureTracker : MonoBehaviour {
private bool fingerIsDown = false;
private Vector3 touchStart;
private Vector3 touchEnd;
private float deviationCheckDistance = 5.0f;
private Vector3 lastDeviationCheck = Vector3.zero;
public float touchPatternResetTime = 3.0f;
private float touchPatternTime = 0.0f;
private string touchPattern = "";
private string touchPatternChain = "";
// pattern chains
private string[] slashUpChain = new string[5] { "4", "41", "42", "14", "24" };
private string[] crossSlashChain = new string[6] { "13,23", "23,13", "32,31", "31,32", "13,32", "32,13" };
private string[] sideSlashChain = new string[2] { "1", "2" };
private string[] circleChain = new string[4] { "23142", "13241", "24132", "14231" };
// registered pattern listeners
private List<GameObject> slashUpListeners = new List<GameObject>();
private List<GameObject> crossSlashListeners = new List<GameObject>();
private List<GameObject> sideSlashListeners = new List<GameObject>();
private List<GameObject> circleListeners = new List<GameObject>();
void Update() {
// touch start
if (!fingerIsDown && Input.GetButtonDown("Fire1")) {
fingerIsDown = true;
touchStart = Camera.main.ScreenToWorldPoint(Input.mousePosition);
touchStart.z = -1;
lastDeviationCheck = touchStart;
}
// touch middle
if (fingerIsDown && Input.GetButton("Fire1")) {
touchPatternTime = 0.0f; // reset touch pattern time
Vector3 touchCurrent = Camera.main.ScreenToWorldPoint(Input.mousePosition);
float diffX = Mathf.Abs(touchCurrent.x - lastDeviationCheck.x);
float diffY = Mathf.Abs(touchCurrent.y - lastDeviationCheck.y);
bool deviated = false;
if (diffX > deviationCheckDistance) {
// RIGHT -> LEFT
if (touchCurrent.x > lastDeviationCheck.x) {
RecordPattern("1");
deviated = true;
}
// LEFT -> RIGHT
if (touchCurrent.x < lastDeviationCheck.x) {
RecordPattern("2");
deviated = true;
}
}
if (diffY > deviationCheckDistance) {
// TOP -> BOTTOM
if (touchCurrent.y < lastDeviationCheck.y) {
RecordPattern("3");
deviated = true;
}
// BOTTOM -> TOP
if (touchCurrent.y > lastDeviationCheck.y) {
RecordPattern("4");
deviated = true;
}
}
if (deviated) {
lastDeviationCheck = touchCurrent;
}
}
// touch end
if (fingerIsDown && Input.GetButtonUp("Fire1")) {
fingerIsDown = false;
touchEnd = Camera.main.ScreenToWorldPoint(Input.mousePosition);
touchEnd.z = -1;
// check patterns on mouse up
if (touchPattern != "") {
ProcessPattern(touchPattern);
}
}
touchPatternTime += 0.1f;
// if we are over the pattern matching time limit the user did something else
if (touchPatternTime > touchPatternResetTime) {
ResetPattern();
}
}
void RecordPattern(string thisPattern) {
switch (touchPattern.Length) {
case 0:
touchPattern += thisPattern;
break;
case 1:
if (thisPattern != touchPattern) {
touchPattern += thisPattern;
}
break;
default:
string lastCheck1 = touchPattern.Substring(touchPattern.Length - 2, 1);
string lastCheck2 = touchPattern.Substring(touchPattern.Length - 2, 2);
if (thisPattern != lastCheck1 && lastCheck1 + thisPattern != lastCheck2) {
touchPattern += thisPattern;
}
break;
}
}
void ResetTouch() {
touchPatternTime = 0.0f;
touchPattern = "";
}
void ResetPattern() {
touchPatternChain = "";
ResetTouch();
}
void ProcessPattern(string pattern) {
ResetTouch();
if (touchPatternChain.Length > 0) {
touchPatternChain += "," + pattern;
} else {
touchPatternChain = pattern;
}
// slash up
foreach (string chain in slashUpChain) {
if (touchPatternChain == chain) {
ResetPattern();
ProcessSlashUp();
return;
}
}
// cross slash
foreach (string chain in crossSlashChain) {
if (touchPatternChain == chain) {
ResetPattern();
ProcessCrossSlash();
return;
}
}
// side slash
foreach (string chain in sideSlashChain) {
if (touchPatternChain == chain) {
ResetPattern();
ProcessSideSlash();
return;
}
}
// circle
foreach (string chain in circleChain) {
if (touchPatternChain == chain) {
ResetPattern();
ProcessCircle();
return;
}
}
}
void ProcessSlashUp() {
for (int i = 0; i < slashUpListeners.Count; i++) {
slashUpListeners[i].SendMessage("Activate", touchEnd);
}
}
void ProcessCrossSlash() {
for (int i = 0; i < crossSlashListeners.Count; i++) {
crossSlashListeners[i].SendMessage("Activate");
}
}
void ProcessSideSlash() {
Vector3[] sendParams = new Vector3[2] { touchStart, touchEnd };
for (int i = 0; i < sideSlashListeners.Count; i++) {
sideSlashListeners[i].SendMessage("Activate", sendParams);
}
}
void ProcessCircle() {
for (int i = 0; i < circleListeners.Count; i++) {
circleListeners[i].SendMessage("Activate");
}
}
public void RegisterSlashUpListener(GameObject listener) {
slashUpListeners.Add(listener);
}
public void RegisterCrossSlashListener(GameObject listener) {
crossSlashListeners.Add(listener);
}
public void RegisterSideSlashListener(GameObject listener) {
sideSlashListeners.Add(listener);
}
public void RegisterCircleListener(GameObject listener) {
circleListeners.Add(listener);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment