Swipe Detection in Unity 5

By June 19, 2017Dev Blog

So recently I’ve been playing around with creating swipe controls for mobile games. I’m going to talk you through my implementation explaining how it works. I used this swipe detection in my mobile game Blocks.

Blocks is a simplistic 2.5D puzzle game where you swipe to move the player over all blocks in the level.

Here’s some footage of the game:

Get it on Google Play

Okay so lets get started. The first thing we will need is an enumerator, this will help us easily store the direction the swipe is in.

 public enum SwipeDirection
 {
     Up,
     Down,
     Left,
     Right,
     None
 }

So, now we have our base enum set up to associate each direction with. The next thing we should do is create a function which will input two Vector 2’s and return a SwipeDirection. So lets call this something relevant, for example

SwipeDirection GetSwipeDirection(Vector2 start, Vector2 end)

The first thing we need to do in this function is figure out the swipe length in Vector 2 form. We will then take this Vector 2 and normalize it. This can be done in the following fashion;

Vector2 swipeLength = new Vector2(end.x - start.x, end.y - start.y);
swipeLength.Normalize();

After we have normalized the Vector, we can then proceed to checking which direction the swipe is going. To do this, we will also need a float to act as our swipe threshold. This will stop all swipes just being on direction.

Near the top of your script add the following:

[SerializedField]
private float swipeThreshold = 0.25f;

Serializing a private field will allow us to adjust the value within the editor, while still concealing it within the class. Now that we have our swipe threshold value, we can proceed to checking the direction of the swipe

if(swipeLength.y > 0 && swipeLength.x > -swipeThreshold && swipeLength.x < swipeThreshold)
{
    return SwipeDirection.Up; //The y is over 0 and the the x margins are within the threshold
}
else if(swipeLength.y < 0 && swipeLength.x > -swipeThreshold && swipeLength.x < swipeThreshold)
{
    return SwipeDirection.Down; // The y is under 0 and the x margins are within the threshold
}
else if(swipeLength.x > 0 && swipeLength.y > -swipeThreshold && swipeLength.y < swipeThreshold)
{
    return SwipeDirection.Left; //The x is over 0 and the y margins are within the threshold
}
else if(swipeLength.x < 0 && swipeLength.y > -swipeThreshold && swipeLength.y < swipeThreshold)
{
    return swipeDirection.Right; //The x is under 0 and the y margins are within the threshold
}
else 
{
    return SwipeDirection.None; //No swipe found within boundaries
}

This code will check the contents of the swipeLength Vector and check it against the requirements for a swipe.

 

 

So our final code for this function should look something like this:

SwipeDirection GetSwipeDirection(Vector2 start, Vector2 end)
{
    Vector2 swipeLength = new Vector2(end.x - start.x, end.y - start.y);
    swipeLength.Normalize();
    if(swipeLength.y > 0 && swipeLength.x > -swipeThresehold && swipeLength.x < swipeThresehold)
    {
        return SwipeDirection.Up; //The y is over 0 and the x margins are within the threshold
    }
    else if(swipeLength.y < 0 && swipeLength.x > -swipeThresehold && swipeLength.x < swipeThresehold)
    {
        return SwipeDirection.Down; //The y is under 0 and the y margins are within the threshold
    }
    else if(swipeLength.x > 0 && swipeLength.y > -swipeThresehold && swipeLength.y < swipeThresehold)
    {
        return SwipeDirection.Left; //The x is over 0 and the y margins are within the threshold
    }
    else if(swipeLength.x < 0 && swipeLength.y > -swipeThresehold && swipeLength.y < swipeThresehold)
    {
        return SwipeDirection.Right; //The x is under 0 and the y margins are within the threshold
    }
    else 
    {
        return SwipeDirection.None; //No swipe found within boundaries
    }
}

Now that we have a method for checking the direction of the swipe, we need to create the method for getting the swipe. Within this method we will use a switch statement to run through the different phases of a touch.

Firstly we will need to create a variable for storing our swipe into. Near the top of your script, just below the class definition, put the following

private SwipeDirection currentSwipe;

We will also need two Vector 2’s which will be used to determine the beginning point and the end point of the touch. Just below the previous declaration add the following

private Vector2 touchStart, touchEnd;

Finally the third thing we will need before starting to write our function, are two more floats which determine the minimum swipe height and width. We can use the devices screen height and width to set these values within the Start function of the script.

private float minSwipeHeight, minSwipeWidth;

void Start()
{
    minSwipeHeight = Screen.height * 20 / 100; // 20% of the screen height
    minSwipeWidth = Screen.width * 30 / 100; // 30% of the screen width
}

Now lets create a descriptive name for our function, I went with

void CheckForSwipe()

Now we need to first check to see if there is a touch, we can do this by using the following if statement

if(Input.touchcount > 0)

Next add the following to the function

currentSwipe = SwipeDirection.None;
Touch touch = Input.touches[0];

What we are doing here, is ensuring that there is no currentSwipe Recorded. We are then storing the current touch into a variable for use within our switch statement.

We can now proceed on to make our switch statement

switch(touch.phase)
{
    case TouchPhase.Began:
        touchStart = touch.position;
        break;
    case TouchPhase.Ended:
        touchEnd = touch.position;
        if(Mathf.Abs(touchEnd.x - touchStart.x) > minSwipeWidth || Mathf.Abs(touchEnd.y - touchStart.y) > minSwipeHeight)
        {
            currentSwipe = GetSwipeDirection(touchStart, touchEnd);
        }
        break;
    default:
        break;
}

When the touch begins, we are storing the touch location into the touchStart Vector 2. We are also storing the end location of the touch within the touchEnd Vector 2. We then check if the difference between the end and start x values is more than the minimum horizontal swipe value or if the difference between the end and start of the y values is more than the minimum vertical swipe value.

If either of these return true, we then use our GetSwipeDirection function to return the direction the swipe was.

The reason we use Mathf.Abs  is to ensure we get a positive value out of the sum.

Now that we have completed the script, we should have something resembling this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum SwipeDirection
{
    Up,
    Down,
    Left,
    Right,
    None
}

public class SwipeController : MonoBehaviour 
{
    private Vector2 touchStart, touchEnd; //Used for the touch locations

    private float minSwipeHeight, minSwipeWidth; //Set in the Start function

    public SwipeDirection currentSwipe; // Used to store the current swipe

    [SerializeField]
    private float swipeThresehold = 0.25f; //Used to determine the margins of a swipe

    void Start ()
    {
        currentSwipe = SwipeDirection.None; // Ensures the variable is not set
        minSwipeHeight = Screen.height * 20 / 100; // 20% of the devices screen height
        minSwipeWidth = Screen.width * 30 / 100; // 30% of the devices screen width 
    } 

    void FixedUpdate () 
    {
        CheckForSwipe(); 
    }

    void CheckForSwipe()
    {
        if(Input.touchCount > 0)
        {
            currentSwipe = SwipeDirection.None; // Ensures the variable is not set
            Touch touch = Input.touches[0];
            switch(touch.phase)
            {
                 case TouchPhase.Began:
                    touchStart = touch.position; 
                    break;
                case TouchPhase.Ended:
                    touchEnd = touch.position;
                    if (Mathf.Abs(touchEnd.x - touchStart.x) > minSwipeWidth || Mathf.Abs(touchEnd.y - touchStart.y) > minSwipeHeight)
                    {
                        currentSwipe = GetSwipeDirection(touchStart, touchEnd);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    SwipeDirection GetSwipeDirection(Vector2 start, Vector2 end)
    {
        Vector2 swipeLength = new Vector2(end.x - start.x, end.y - start.y);
        swipeLength.Normalize();

        if(swipeLength.y > 0 && swipeLength.x > -swipeThresehold && swipeLength.x < swipeThresehold)
        {
            return SwipeDirection.Up; //The y is over 0 and the x margins are within the threshold
        }
        else if(swipeLength.y < 0 && swipeLength.x > -swipeThresehold && swipeLength.x < swipeThresehold)
        {
            return SwipeDirection.Down; //The y is under 0 and the y margins are within the threshold
        }
        else if(swipeLength.x > 0 && swipeLength.y > -swipeThresehold && swipeLength.y < swipeThresehold)
        {
            return SwipeDirection.Left; //The x is over 0 and the y margins are within the threshold
        }
        else if(swipeLength.x < 0 && swipeLength.y > -swipeThresehold && swipeLength.y < swipeThresehold)
        {
            return SwipeDirection.Right; //The x is under 0 and the y margins are within the threshold
        } 
        else
        {
            return SwipeDirection.None; //No swipe found within boundaries
        }
    }
}

Thanks for reading, and I hope you enjoyed this blog post about Swipe Detection within Unity.

Leave a Reply