Detect swipe gesture direction
That is my code to try and simulate a swipe gesture so when I build to mobile I know it will work. Nothing is being logged and I am confused on why it seems to not work. I want it to print out in the console that I either swiped RTL
(Right to Left) or LTR
(Left to right). I do not see what I am doing wrong.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
startPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
if (Input.GetMouseButtonUp(0))
{
endPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
if (startPosition != endPosition && startPosition != Vector3.zero && endPosition != Vector3.zero)
{
float deltaX = endPosition.x - startPosition.x;
float deltaY = endPosition.y - startPosition.y;
if ((deltaX > 5.0f || deltaX < -5.0f) && (deltaY >= -1.0f || deltaY <= 1.0f))
{
if (startPosition.x < endPosition.x)
{
print("LTR");
}
else
{
print("RTL");
}
}
startPosition = endPosition = Vector3.zero;
}
}
Solution 1:
I can spot some few problems in your code. It's not a good idea to compare Vector3
with ==
or !=
. Approximate comparison is fine. You are using Input.GetMouseButtonDown
on a mobile platform.
You need to use Input.touches
to do this. Loop over it, store the beginning position in TouchPhase.Began
and then the end position in TouchPhase.Ended
. You can then use both variables to figure it which direction the finger went.
The code below detects swipe direction even when the finger is not yet released with the help of TouchPhase.Moved
. You can disable that by enabling the detectSwipeOnlyAfterRelease
boolean variable. You can also modify SWIPE_THRESHOLD
for sensitivity.
public class SwipeDetector : MonoBehaviour
{
private Vector2 fingerDown;
private Vector2 fingerUp;
public bool detectSwipeOnlyAfterRelease = false;
public float SWIPE_THRESHOLD = 20f;
// Update is called once per frame
void Update()
{
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
fingerUp = touch.position;
fingerDown = touch.position;
}
//Detects Swipe while finger is still moving
if (touch.phase == TouchPhase.Moved)
{
if (!detectSwipeOnlyAfterRelease)
{
fingerDown = touch.position;
checkSwipe();
}
}
//Detects swipe after finger is released
if (touch.phase == TouchPhase.Ended)
{
fingerDown = touch.position;
checkSwipe();
}
}
}
void checkSwipe()
{
//Check if Vertical swipe
if (verticalMove() > SWIPE_THRESHOLD && verticalMove() > horizontalValMove())
{
//Debug.Log("Vertical");
if (fingerDown.y - fingerUp.y > 0)//up swipe
{
OnSwipeUp();
}
else if (fingerDown.y - fingerUp.y < 0)//Down swipe
{
OnSwipeDown();
}
fingerUp = fingerDown;
}
//Check if Horizontal swipe
else if (horizontalValMove() > SWIPE_THRESHOLD && horizontalValMove() > verticalMove())
{
//Debug.Log("Horizontal");
if (fingerDown.x - fingerUp.x > 0)//Right swipe
{
OnSwipeRight();
}
else if (fingerDown.x - fingerUp.x < 0)//Left swipe
{
OnSwipeLeft();
}
fingerUp = fingerDown;
}
//No Movement at-all
else
{
//Debug.Log("No Swipe!");
}
}
float verticalMove()
{
return Mathf.Abs(fingerDown.y - fingerUp.y);
}
float horizontalValMove()
{
return Mathf.Abs(fingerDown.x - fingerUp.x);
}
//////////////////////////////////CALLBACK FUNCTIONS/////////////////////////////
void OnSwipeUp()
{
Debug.Log("Swipe UP");
}
void OnSwipeDown()
{
Debug.Log("Swipe Down");
}
void OnSwipeLeft()
{
Debug.Log("Swipe Left");
}
void OnSwipeRight()
{
Debug.Log("Swipe Right");
}
}
Solution 2:
Thanks to Programmer, I used his suggestion and wrote a small component which works both with mouse and touch. The mouse will allow you to debug app on PC. I also added time threshold in seconds, since swipe cannot be too long.
using System;
using UnityEngine;
using UnityEngine.Events;
public class SwipeManager : MonoBehaviour {
public float swipeThreshold = 50f;
public float timeThreshold = 0.3f;
public UnityEvent OnSwipeLeft;
public UnityEvent OnSwipeRight;
public UnityEvent OnSwipeUp;
public UnityEvent OnSwipeDown;
private Vector2 fingerDown;
private DateTime fingerDownTime;
private Vector2 fingerUp;
private DateTime fingerUpTime;
private void Update () {
if (Input.GetMouseButtonDown(0)) {
this.fingerDown = Input.mousePosition;
this.fingerUp = Input.mousePosition;
this.fingerDownTime = DateTime.Now;
}
if (Input.GetMouseButtonUp(0)) {
this.fingerDown = Input.mousePosition;
this.fingerUpTime = DateTime.Now;
this.CheckSwipe();
}
foreach (Touch touch in Input.touches) {
if (touch.phase == TouchPhase.Began) {
this.fingerDown = touch.position;
this.fingerUp = touch.position;
this.fingerDownTime = DateTime.Now;
}
if (touch.phase == TouchPhase.Ended) {
this.fingerDown = touch.position;
this.fingerUpTime = DateTime.Now;
this.CheckSwipe();
}
}
}
private void CheckSwipe() {
float duration = (float)this.fingerUpTime.Subtract(this.fingerDownTime).TotalSeconds;
if (duration > this.timeThreshold) return;
float deltaX = this.fingerDown.x - this.fingerUp.x;
if (Mathf.Abs(deltaX) > this.swipeThreshold) {
if (deltaX > 0) {
this.OnSwipeRight.Invoke();
//Debug.Log("right");
} else if (deltaX < 0) {
this.OnSwipeLeft.Invoke();
//Debug.Log("left");
}
}
float deltaY = fingerDown.y - fingerUp.y;
if (Mathf.Abs(deltaY) > this.swipeThreshold) {
if (deltaY > 0) {
this.OnSwipeUp.Invoke();
//Debug.Log("up");
} else if (deltaY < 0) {
this.OnSwipeDown.Invoke();
//Debug.Log("down");
}
}
this.fingerUp = this.fingerDown;
}
}