Simple swipe and tap mobile input

I couldn’t find a decent working example of basic swipe and tap input using recent unity versions (as of this writing this works with 5.3 unity) so I went ahead and cobbled a simple snippet together that basically handles it. It isn’t heavily battle tested and might not be perfect, but seems to work from the 5 minutes or so of testing I did. Original credit goes to Sujit Horakeri of “the game contriver”.

EDIT: Note - if you want 8 directional movement and mouse “touch simulation” check the later posts!

Adapted from here:
http://www.thegamecontriver.com/2014/08/unity3d-swipe-input-for-touch-screen.html

Anyway here she be, ready to go in unity 5.3:

    private Vector3 fp;   //First touch position
    private Vector3 lp;   //Last touch position
    private float dragDistance;  //minimum distance for a swipe to be registered

    void Start()
    {
        dragDistance = Screen.height * 15 / 100; //dragDistance is 15% height of the screen
    }

    void Update()
    {
        if (Input.touchCount == 1) // user is touching the screen with a single touch
        {
            Touch touch = Input.GetTouch(0); // get the touch
            if (touch.phase == TouchPhase.Began) //check for the first touch
            {
                fp = touch.position;
                lp = touch.position;
            }
            else if (touch.phase == TouchPhase.Moved) // update the last position based on where they moved
            {
                lp = touch.position;
            }
            else if (touch.phase == TouchPhase.Ended) //check if the finger is removed from the screen
            {
                lp = touch.position;  //last touch position. Ommitted if you use list

                //Check if drag distance is greater than 20% of the screen height
                if (Mathf.Abs(lp.x - fp.x) > dragDistance || Mathf.Abs(lp.y - fp.y) > dragDistance)
                {//It's a drag
                 //check if the drag is vertical or horizontal
                    if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
                    {   //If the horizontal movement is greater than the vertical movement...
                        if ((lp.x > fp.x))  //If the movement was to the right)
                        {   //Right swipe
                            Debug.Log("Right Swipe");
                        }
                        else
                        {   //Left swipe
                            Debug.Log("Left Swipe");
                        }
                    }
                    else
                    {   //the vertical movement is greater than the horizontal movement
                        if (lp.y > fp.y)  //If the movement was up
                        {   //Up swipe
                            Debug.Log("Up Swipe");
                        }
                        else
                        {   //Down swipe
                            Debug.Log("Down Swipe");
                        }
                    }
                }
                else
                {   //It's a tap as the drag distance is less than 20% of the screen height
                    Debug.Log("Tap");
                }
            }
        }
    }
18 Likes

Maybe you are interested in this script.
Its a Swipe Touch Controller for Android/iOS.

1 Like

While I did look into your product, I wasnt sure it would be right for me, so I ended up moving onto another publicly available script, which I found a sample somewhere here on the forum, that uses 8 directions of movement, allowing up-right, and all other diagonal directions. I’ll post the code to that here for future reference when I get back to my dev machine.

1 Like

Thank you so much!:slight_smile:

1 Like

Hey totally forgot to ever share the 8 directional version! Sorry if anybody had been waiting on that!

This version allows the mouse to emulate touches in the editor (great for debugging and rapid prototyping) and of course has 8 directions of “swipe detection” rather than only 4.

Anyway I didn’t write all of this, and instead found most of this in another topic ( Swipe in all directions Touch and Mouse - Unity Engine - Unity Discussions ), although there might be modifications here and there, it should help get you going in the right direction :stuck_out_tongue:

SwipeManager.cs

using UnityEngine;
using System.Collections;

public struct SwipeAction
{
public SwipeDirection direction;
public Vector2 rawDirection;
public Vector2 startPosition;
public Vector2 endPosition;
public float startTime;
public float endTime;
public float duration;
public bool longPress;
public float distance;
public float longestDistance;

public override string ToString()
{
return string.Format(“[SwipeAction: {0}, From {1}, To {2}, Delta {3}, Time {4:0.00}s]”, direction, rawDirection, startPosition, endPosition, duration);
}
}

public enum SwipeDirection
{
None, // Basically means an invalid swipe
Up,
UpRight,
Right,
DownRight,
Down,
DownLeft,
Left,
UpLeft
}

///


/// Swipe manager.
/// BASED ON: Swipe in all directions Touch and Mouse - Unity Engine - Unity Discussions
///

public class SwipeManager : MonoBehaviour
{
public System.Action onSwipe;
public System.Action onLongPress;

[Range(0f, 200f)]
public float minSwipeLength = 100f;

public float longPressDuration = 0.5f;

Vector2 currentSwipe;
SwipeAction currentSwipeAction = new SwipeAction();

void Update()
{
DetectSwipe();
}

public void DetectSwipe()
{
var touches = InputHelper.GetTouches();
if (touches.Count > 0)
{
Touch t = touches[0];

if (t.phase == TouchPhase.Began)
{
ResetCurrentSwipeAction(t);
}

if (t.phase == TouchPhase.Moved || t.phase == TouchPhase.Stationary)
{
UpdateCurrentSwipeAction(t);
if (!currentSwipeAction.longPress && currentSwipeAction.duration > longPressDuration && currentSwipeAction.longestDistance < minSwipeLength)
{
currentSwipeAction.direction = SwipeDirection.None; // Invalidate current swipe action
currentSwipeAction.longPress = true;
if (onLongPress != null)
{
onLongPress(currentSwipeAction); // Fire event
}
return;
}
}

if (t.phase == TouchPhase.Ended)
{
UpdateCurrentSwipeAction(t);

// Make sure it was a legit swipe, not a tap, or long press
if (currentSwipeAction.distance < minSwipeLength || currentSwipeAction.longPress) // Didnt swipe enough or this is a long press
{
currentSwipeAction.direction = SwipeDirection.None; // Invalidate current swipe action
return;
}

if (onSwipe != null)
{
onSwipe(currentSwipeAction); // Fire event
}
}
}
}

void ResetCurrentSwipeAction(Touch t)
{
currentSwipeAction.duration = 0f;
currentSwipeAction.distance = 0f;
currentSwipeAction.longestDistance = 0f;
currentSwipeAction.longPress = false;
currentSwipeAction.startPosition = new Vector2(t.position.x, t.position.y);
currentSwipeAction.startTime = Time.time;
currentSwipeAction.endPosition = currentSwipeAction.startPosition;
currentSwipeAction.endTime = currentSwipeAction.startTime;
}

void UpdateCurrentSwipeAction(Touch t)
{
currentSwipeAction.endPosition = new Vector2(t.position.x, t.position.y);
currentSwipeAction.endTime = Time.time;
currentSwipeAction.duration = currentSwipeAction.endTime - currentSwipeAction.startTime;
currentSwipe = currentSwipeAction.endPosition - currentSwipeAction.startPosition;
currentSwipeAction.rawDirection = currentSwipe;
currentSwipeAction.direction = GetSwipeDirection(currentSwipe);
currentSwipeAction.distance = Vector2.Distance(currentSwipeAction.startPosition, currentSwipeAction.endPosition);
if (currentSwipeAction.distance > currentSwipeAction.longestDistance) // If new distance is longer than previously longest
{
currentSwipeAction.longestDistance = currentSwipeAction.distance; // Update longest distance
}
}

SwipeDirection GetSwipeDirection(Vector2 direction)
{
var angle = Vector2.Angle(Vector2.up, direction.normalized); // Degrees
var swipeDirection = SwipeDirection.None;

if (direction.x > 0) // Right
{
if (angle < 22.5f) // 0.0 - 22.5
{
swipeDirection = SwipeDirection.Up;
}
else if (angle < 67.5f) // 22.5 - 67.5
{
swipeDirection = SwipeDirection.UpRight;
}
else if (angle < 112.5f) // 67.5 - 112.5
{
swipeDirection = SwipeDirection.Right;
}
else if (angle < 157.5f) // 112.5 - 157.5
{
swipeDirection = SwipeDirection.DownRight;
}
else if (angle < 180.0f) // 157.5 - 180.0
{
swipeDirection = SwipeDirection.Down;
}
}
else // Left
{
if (angle < 22.5f) // 0.0 - 22.5
{
swipeDirection = SwipeDirection.Up;
}
else if (angle < 67.5f) // 22.5 - 67.5
{
swipeDirection = SwipeDirection.UpLeft;
}
else if (angle < 112.5f) // 67.5 - 112.5
{
swipeDirection = SwipeDirection.Left;
}
else if (angle < 157.5f) // 112.5 - 157.5
{
swipeDirection = SwipeDirection.DownLeft;
}
else if (angle < 180.0f) // 157.5 - 180.0
{
swipeDirection = SwipeDirection.Down;
}
}

return swipeDirection;
}
}

InputHelper.cs

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

///


/// Input helper.
/// SOURCE: http://answers.unity3d.com/answers/956579/view.html
///

public static class InputHelper
{
private static TouchCreator lastFakeTouch;

public static List GetTouches()
{
List touches = new List();
touches.AddRange(Input.touches);
// Uncomment if you want it only to allow mouse swipes in the Unity Editor
//#if UNITY_EDITOR
if (lastFakeTouch == null)
{
lastFakeTouch = new TouchCreator();
}
if (Input.GetMouseButtonDown(0))
{
lastFakeTouch.phase = TouchPhase.Began;
lastFakeTouch.deltaPosition = new Vector2(0, 0);
lastFakeTouch.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
lastFakeTouch.fingerId = 0;
}
else if (Input.GetMouseButtonUp(0))
{
lastFakeTouch.phase = TouchPhase.Ended;
Vector2 newPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
lastFakeTouch.deltaPosition = newPosition - lastFakeTouch.position;
lastFakeTouch.position = newPosition;
lastFakeTouch.fingerId = 0;
}
else if (Input.GetMouseButton(0))
{
lastFakeTouch.phase = TouchPhase.Moved;
Vector2 newPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
lastFakeTouch.deltaPosition = newPosition - lastFakeTouch.position;
lastFakeTouch.position = newPosition;
lastFakeTouch.fingerId = 0;
}
else
{
lastFakeTouch = null;
}
if (lastFakeTouch != null)
{
touches.Add(lastFakeTouch.Create());
}
// Uncomment if you want it only to allow mouse swipes in the Unity Editor
//#endif

return touches;
}
}

TouchCreator.cs

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

///


/// Touch creator.
/// BASED ON: http://answers.unity3d.com/answers/801637/view.html
///

public class TouchCreator
{
static BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
static Dictionary<string, FieldInfo> fields;

object touch;

public float deltaTime { get { return ((Touch)touch).deltaTime; } set { fields[“m_TimeDelta”].SetValue(touch, value); } }
public int tapCount { get { return ((Touch)touch).tapCount; } set { fields[“m_TapCount”].SetValue(touch, value); } }
public TouchPhase phase { get { return ((Touch)touch).phase; } set { fields[“m_Phase”].SetValue(touch, value); } }
public Vector2 deltaPosition { get { return ((Touch)touch).deltaPosition; } set { fields[“m_PositionDelta”].SetValue(touch, value); } }
public int fingerId { get { return ((Touch)touch).fingerId; } set { fields[“m_FingerId”].SetValue(touch, value); } }
public Vector2 position { get { return ((Touch)touch).position; } set { fields[“m_Position”].SetValue(touch, value); } }
public Vector2 rawPosition { get { return ((Touch)touch).rawPosition; } set { fields[“m_RawPosition”].SetValue(touch, value); } }

public Touch Create()
{
return (Touch)touch;
}

public TouchCreator()
{
touch = new Touch();
}

static TouchCreator()
{
fields = new Dictionary<string, FieldInfo>();
foreach (var f in typeof(Touch).GetFields(flags))
{
fields.Add(f.Name, f);
//Debug.Log("name: " + f.Name); // Use this to find the names of hidden private fields
}
}
}

InputController.cs - ATTACH TO A GAMEOBJECT! MODIFY TO MEET YOUR NEEDS!

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

[RequireComponent(typeof(SwipeManager))]
public class InputController : MonoBehaviour
{
public Player OurPlayer; // Perhaps your playerscript?

void Start()
{
SwipeManager swipeManager = GetComponent();
swipeManager.onSwipe += HandleSwipe;
swipeManager.onLongPress += HandleLongPress;
}

void HandleSwipe(SwipeAction swipeAction)
{
//Debug.LogFormat(“HandleSwipe: {0}”, swipeAction);
if(swipeAction.direction == SwipeDirection.Up || swipeAction.direction == SwipeDirection.UpRight)
{
// move up
if(OurPlayer != null)
OurPlayer.MovePlayerUp();
}
else if (swipeAction.direction == SwipeDirection.Right || swipeAction.direction == SwipeDirection.DownRight)
{
// move right
if (OurPlayer != null)
OurPlayer.MovePlayerRight();
}
else if (swipeAction.direction == SwipeDirection.Down || swipeAction.direction == SwipeDirection.DownLeft)
{
// move down
if (OurPlayer != null)
OurPlayer.MovePlayerDown();
}
else if (swipeAction.direction == SwipeDirection.Left || swipeAction.direction == SwipeDirection.UpLeft)
{
// move left
if (OurPlayer != null)
OurPlayer.MovePlayerLeft();
}
}

void HandleLongPress(SwipeAction swipeAction)
{
//Debug.LogFormat(“HandleLongPress: {0}”, swipeAction);
}
}

2 Likes

Why we need this condition:

else if (touch.phase == TouchPhase.Moved) // update the last position based on where they moved
{
    lp = touch.position;
}

?

That section just updates the lp to the new location the “touch.phase = TouchPhase.Moved” informs the program that the finger has moved from it’s location, and thus it updates the lp to the new touch.position.

Thanks dude, saved me some time.

Thank you for this. It was a great starting point. I tweaked it in a few places to suit my needs. First I added code to process a swipe in the moved event as well as the ended event. That way you don’t have to wait for the swipe to complete to be considered a swipe. Once it is at 15 percent, it’s a swipe. In order to make it so the ended event didn’t also process a swipe that was handled by the moved, I added a boolean. Lastly, I added the condition for (Mathf.Abs(lp.y - fp.y) > dragDistance) into the swipe up/down logic because we used an OR at the top of the swipe’s if statement, so we’re really not sure what got us there (left/right or up/down). This really only help’s prevent false down swipes which I was seeing on occasion. I did the same for the left/right with the x axis. If anyone wants my code for it, let me know.

hi ephdot, please share your code ,it would help me and others,

thanks too all

1 Like

I’m new to Unity but where in the code does it tell unity what object to move to the finger position? I’m making a pong game and trying to get the paddle to go up and down through touch.

public float paddleSpeed = 1;
public Vector3 playerPos;

private Vector2 touchOrigin = -Vector2.one;

// Update is called once per frame
void Update()
{
float yPos = gameObject.transform.position.y + (Input.GetAxis(“Vertical”) * paddleSpeed);
playerPos = new Vector3(-10, Mathf.Clamp(yPos, -18f, 10f), 0);
gameObject.transform.position = playerPos;

}

This is what i have for the movement right now, but this is just keyboard

Hi, i tried the code below and it worked, when i swipe my object moves, but it takes time ebfore it moves, its not smooth. How can i fix it?

You sir are a saint.
Thank you very much for this script it has saved me a ton of work, THANK YOU!

1 Like

No problem, glad I could help! :slight_smile:

1 Like

Please share the new version.

Sorry - I just saw this.

I abandoned swipe gestures and went with buttons for Jump/Duck.

I just checked and I must have tossed out the swipe script. My apologies.

How do i make controls for Android

Yes.

1 Like

Thank you very much! Very helpful code!

1 Like

No problem, good luck!