Search Unity

Quick Swipe (left or right) || Drag Gesture (Solution)

Discussion in 'iOS and tvOS' started by imparare, Mar 25, 2010.

  1. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Here is some code I just finished that allows for either a swipe or a drag. I have not tested it extensively. It's very easy to set up for use and will detect left and right swipes or drags (depending upon the time you set). It works (or should) for as many touches as you want to place on the screen (it will only pick up one touch out of all the touches). If you use it and it works fine then let me know. If there are issues then I am sure I can get around to looking at them.

    Code (csharp):
    1. /*
    2. Swipe gesture for iPhone. Add this script and a GUIText component to an empty GO
    3. With the GO selected in the inspector set:
    4.  
    5. swipeLength ---> this is how long you want the swipe to be. 25 pixels seems ok
    6. swipeVariance ---> this is how far the drag can go 'off line'. 5 pixels either way seems ok
    7. timeToSwipe ---> if you leave this at 0 then there is no timer. If you set it then this is how long
    8.                     the user has to complete the swipe gesture
    9.  
    10. You can swipe as many fingers left or right and it will only pick up one of them
    11. It will then allow further swipes when that finger has been lifed from the screen.
    12. Typically its swipe > lift finger > swipe .......
    13.  
    14. Be aware that it sometimes does not pick up the iPhoneTouchPhase.Ended
    15. This is either a bug in the logic (plz test) or as the TouchPhases are notoriously
    16. inaccurate its could well be this or it could be iPhone 1.6 given that it is quirky with touches.
    17. Anyhow it does not affect the working of the class
    18. other than a dead once in a while which then rectifies itself on the next swipe so
    19. no big deal.
    20.  
    21. No need for orientation as it will respect whatever you set.
    22. */
    23.  
    24. using UnityEngine;
    25. using System.Collections;
    26.  
    27. public class TouchInfo
    28. {
    29.     public Vector2 touchPosition;
    30.     public bool swipeComplete;
    31.     public float timeSwipeStarted;
    32. }
    33.  
    34.  
    35. public class SwipeDrag : MonoBehaviour {
    36.  
    37. //public member vars
    38. public int swipeLength;
    39. public int swipeVariance;
    40. public float timeToSwipe;
    41. //private member vars
    42. private GUIText swipeText;
    43. private TouchInfo[] touchInfoArray;
    44. private int activeTouch = -1;
    45.  
    46. //methods
    47.     void Start()
    48.     {
    49.         //get a reference to the GUIText component
    50.         swipeText = (GUIText) GetComponent(typeof(GUIText));
    51.         touchInfoArray = new TouchInfo[5];
    52.     }  
    53.  
    54.     void Update()
    55.     {
    56.         //touch count is a bit dodgy at the moment so add the extra check to see if there are no more than 5 touches
    57.         if(iPhoneInput.touchCount > 0  iPhoneInput.touchCount < 6)
    58.         {
    59.             foreach(iPhoneTouch touch in iPhoneInput.touches)
    60.             {
    61.                 if(touchInfoArray[touch.fingerId] == null)
    62.                         touchInfoArray[touch.fingerId] = new TouchInfo();
    63.                        
    64.                 if(touch.phase == iPhoneTouchPhase.Began)
    65.                 {
    66.                     touchInfoArray[touch.fingerId].touchPosition = touch.position;
    67.                     touchInfoArray[touch.fingerId].timeSwipeStarted = Time.time;
    68.                 }
    69.                 //check if withing swipe variance      
    70.                 if(touch.position.y > (touchInfoArray[touch.fingerId].touchPosition.y + swipeVariance))
    71.                 {
    72.                     touchInfoArray[touch.fingerId].touchPosition = touch.position;
    73.                 }
    74.                 if(touch.position.y < (touchInfoArray[touch.fingerId].touchPosition.y - swipeVariance))
    75.                 {
    76.                     touchInfoArray[touch.fingerId].touchPosition = touch.position;
    77.                 }
    78.                 //swipe right
    79.                 if((touch.position.x > touchInfoArray[touch.fingerId].touchPosition.x + swipeLength)  !touchInfoArray[touch.fingerId].swipeComplete
    80.                      activeTouch == -1)
    81.                 {
    82.                     SwipeComplete("swipe right  ",  touch);
    83.                 }
    84.                 //swipe left
    85.                 if((touch.position.x < touchInfoArray[touch.fingerId].touchPosition.x - swipeLength)  !touchInfoArray[touch.fingerId].swipeComplete
    86.                      activeTouch == -1)
    87.                 {
    88.                         SwipeComplete("swipe left  ",  touch);
    89.                 }
    90.                 //when the touch has ended we can start accepting swipes again
    91.                 if(touch.fingerId == activeTouch  touch.phase == iPhoneTouchPhase.Ended)
    92.                 {
    93.                     //Debug.Log("Ending " + touch.fingerId);
    94.                     //if more than one finger has swiped then reset the other fingers so
    95.                     //you do not get a double/triple etc. swipe
    96.                     foreach(iPhoneTouch touchReset in iPhoneInput.touches)
    97.                     {
    98.                         touchInfoArray[touch.fingerId].touchPosition = touchReset.position;
    99.                     }
    100.                     touchInfoArray[touch.fingerId].swipeComplete = false;
    101.                     activeTouch = -1;
    102.                 }
    103.             }          
    104.         }  
    105.     }
    106.    
    107.     void SwipeComplete(string messageToShow, iPhoneTouch touch)
    108.     {
    109.         //Debug.Log(Time.time - touchInfoArray[touch.fingerId].timeSwipeStarted);
    110.         Reset(touch);
    111.         if(timeToSwipe == 0.0f || (timeToSwipe > 0.0f  (Time.time - touchInfoArray[touch.fingerId].timeSwipeStarted) <= timeToSwipe))
    112.         {
    113.             swipeText.text = messageToShow;
    114.             //Do something here
    115.         }
    116.     }
    117.    
    118.     void Reset(iPhoneTouch touch)
    119.     {
    120.         activeTouch = touch.fingerId;
    121.         touchInfoArray[touch.fingerId].swipeComplete = true;       
    122.     }
    123.    
    124. }
     
    arash-k likes this.
  2. minevr

    minevr

    Joined:
    Mar 4, 2008
    Posts:
    1,018
    Ok,it's working.... :twisted:
     
  3. Hakimo

    Hakimo

    Joined:
    Apr 29, 2010
    Posts:
    316
    Hi, your code works fine thanks. I'm currently testing it out with a few scenarios. How to I assign a collision area for the touchevent to trigger? Meaning I only want the gesture thing to work when your finger is in the plane area instead of the whole screen.

    Thanks in advance.

    -Hakimo
     
  4. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Use a raycast to check that the object (your plane with a collider) is being touched.

    Look up ScreenPointToRay in the docs.
     
  5. hizral

    hizral

    Joined:
    Apr 27, 2010
    Posts:
    568
    I've try the code and it's working, but how do I make the input touch play the animation one at a time each time I swipe the screen....

    right now if I swipe the screen rapidly it will reset the animation over and over again.

    how do I code when I swipe once the code disable and after the animation finish the code enable again.
     
  6. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Just check for

    if(!animation.isPlaying) //then check for finger touches.

    Assuming the swipe is on the same GO as the animation otherwise just change animation to your animation reference so: (!myAnimation.isPlaying)
     
  7. Hakimo

    Hakimo

    Joined:
    Apr 29, 2010
    Posts:
    316
    Hi,

    This is about the quick swipe code. Instead of just swiping left and right, I'm trying to create something where you have to swipe left and right continuously to activate something. Kind of like a rubbing effect.

    How should I approach this? I was thinking of using a for loop and creating a counter to set how many times it should be swiped before being activated. Need a second opinion if there's an optimal solution.

    Thank you.
    -Hakimo
     
  8. imparare

    imparare

    Joined:
    Jun 24, 2008
    Posts:
    369
    Hi Hakimo,

    it's not that straightforward. You can adapt the swipe code here but before doing that you need to decide how the game works. How many fingers can the player have on screen ? Is it just a rub game or does the player have to do other stuff as well? If it's other stuff as well then you need to detect when a rub can occur so you are not constantly checking for a rub when you do not need to etc.

    Creating a rub from the existing code would mean knocking out a few lines because at present you have to swipe > lift finger > swipe but with rub its swipe > swipe > swipe. This is straightforward and to finish it off you only need a counter to count the left swipes and the right swipes then when you hit your magic swipe number you can do something and reset the rub count.

    As I say it really has to be tailored for the type of gameplay you have in mind.
     
  9. groovfruit

    groovfruit

    Joined:
    Apr 26, 2010
    Posts:
    257
    Has anyone managed or able to translate this to JS? I'm not a coder - I gave it a shot but failed miserably :p Cheers.
     
  10. Hakimo

    Hakimo

    Joined:
    Apr 29, 2010
    Posts:
    316
    Hi Imparare,

    Thanks for the reply, actually for the game I'm making, I'm going to have both functions as in swipe > lift finger > swipe for vertical and swipe > swipe > swipe for horizontal.

    You said knocking out a few lines? Which is it? I thought I have to edit the activeTouch? Also I think I need to add another condition to avoid "when the touch is ended". Lol, I'm not really sure now. I'll try and see if I can work something out.

    Thanks again.
    - Hakimo
     
  11. groovfruit

    groovfruit

    Joined:
    Apr 26, 2010
    Posts:
    257
    Anyone? Anyone at all? :( I need help!
     
  12. _ivansc

    _ivansc

    Joined:
    Mar 27, 2012
    Posts:
    14
    i know its from 2010... but heres the JS version

    Code (csharp):
    1.  
    2. #pragma strict
    3.  
    4. public class TouchInfo
    5. {
    6.     public var touchPosition : Vector2;
    7.     public var swipeComplete;
    8.     public var timeSwipeStarted : float;
    9. }
    10.  
    11.  
    12. //public member vars
    13. public var swipeLength : int;
    14. public var swipeVariance : int;
    15. public var timeToSwipe : float;
    16.  
    17. //private member vars
    18. private var swipeText: GUIText;
    19. private var touchInfoArray : TouchInfo[];
    20. private var activeTouch : int = -1;
    21.  
    22.  
    23. function Update()
    24. {
    25.     //touch count is a bit dodgy at the moment so add the extra check to see if there are no more than 5 touches
    26.     if(iPhoneInput.touchCount > 0  iPhoneInput.touchCount < 6)
    27.     {
    28.         for(touch in iPhoneInput.touches)
    29.         {
    30.             if(touchInfoArray[touch.fingerId] == null)
    31.                     touchInfoArray[touch.fingerId] = new TouchInfo();
    32.  
    33.             if(touch.phase == iPhoneTouchPhase.Began)
    34.             {
    35.                 touchInfoArray[touch.fingerId].touchPosition = touch.position;
    36.                 touchInfoArray[touch.fingerId].timeSwipeStarted = Time.time;
    37.             }
    38.  
    39.             //check if withing swipe variance      
    40.             if(touch.position.y > (touchInfoArray[touch.fingerId].touchPosition.y + swipeVariance))
    41.             {
    42.                 touchInfoArray[touch.fingerId].touchPosition = touch.position;
    43.             }
    44.  
    45.             if(touch.position.y < (touchInfoArray[touch.fingerId].touchPosition.y - swipeVariance))
    46.             {
    47.                 touchInfoArray[touch.fingerId].touchPosition = touch.position;
    48.             }
    49.  
    50.             //swipe right
    51.             if((touch.position.x > touchInfoArray[touch.fingerId].touchPosition.x + swipeLength)  !touchInfoArray[touch.fingerId].swipeComplete  activeTouch == -1)
    52.             {
    53.                 SwipeComplete("swipe right  ",  touch);
    54.             }
    55.  
    56.             //swipe left
    57.             if((touch.position.x < touchInfoArray[touch.fingerId].touchPosition.x - swipeLength)  !touchInfoArray[touch.fingerId].swipeComplete  activeTouch == -1)
    58.             {
    59.                 SwipeComplete("swipe left  ",  touch);
    60.             }
    61.  
    62.             //when the touch has ended we can start accepting swipes again
    63.             if(touch.fingerId == activeTouch  touch.phase == iPhoneTouchPhase.Ended)
    64.             {
    65.                 //Debug.Log("Ending " + touch.fingerId);
    66.                 //if more than one finger has swiped then reset the other fingers so
    67.                 //you do not get a double/triple etc. swipe
    68.                 for(touchReset in iPhoneInput.touches)
    69.                 {
    70.                     touchInfoArray[touch.fingerId].touchPosition = touchReset.position;
    71.                 }
    72.  
    73.                 touchInfoArray[touch.fingerId].swipeComplete = false;
    74.                 activeTouch = -1;
    75.             }
    76.         }          
    77.     }  
    78. }
    79.  
    80.  
    81.  
    82. function SwipeComplete(messageToShow : String, touch : iPhoneTouch)
    83. {
    84.     //Debug.Log(Time.time - touchInfoArray[touch.fingerId].timeSwipeStarted);
    85.     Reset(touch);
    86.     if(timeToSwipe == 0.0f || (timeToSwipe > 0.0f  (Time.time - touchInfoArray[touch.fingerId].timeSwipeStarted) <= timeToSwipe))
    87.     {
    88.         swipeText.text = messageToShow;
    89.         //Do something here
    90.     }
    91. }
    92.  
    93.  
    94.  
    95. function Reset(touch : iPhoneTouch)
    96. {
    97.     activeTouch = touch.fingerId;
    98.     touchInfoArray[touch.fingerId].swipeComplete = true;        
    99. }
    100.  
     
  13. Hakimo

    Hakimo

    Joined:
    Apr 29, 2010
    Posts:
    316
    Hi ivansc, I just tested your code for fun, there's this error i keep getting "Object reference not set to an instance of an object". Am I missing anything? I added the script to an empty gameObject but not sure why it's giving me the errors.
     
  14. jkrassman

    jkrassman

    Joined:
    Dec 18, 2012
    Posts:
    20
    I am on Unity4 and that gives me an error on this line:

    Code (csharp):
    1. foreach(iPhoneTouch touchReset in iPhoneInput.touches)
    And if I change to Touch instead of iPhoneTouch I am getting this error:

    Cannot convert type `UnityEngine.iPhoneTouch' to `UnityEngine.Touch'

    I am a new beginner with Unity and C# and have no clue what this means? Anyone?

    Joakim
     
  15. Theinsanekiller

    Theinsanekiller

    Joined:
    Jun 1, 2012
    Posts:
    27
    I am making a game android phone, will this same code gonna wok on android phone too???
     
  16. 3dgrinder

    3dgrinder

    Joined:
    Oct 21, 2008
    Posts:
    249
  17. HunterKrech

    HunterKrech

    Joined:
    Aug 22, 2012
    Posts:
    8
    This will work for Android only if you switch everything that says "IPhone" to "Android".
     
  18. jessica1986

    jessica1986

    Joined:
    Feb 7, 2012
    Posts:
    621
    same query, will this code work on both IOS and Android..

    Please someone help us on this.
     
  19. Omer.Hussain

    Omer.Hussain

    Joined:
    Dec 16, 2013
    Posts:
    5
    just remove the iphone it will work for android.. :)
     
  20. RdxC4

    RdxC4

    Joined:
    Jun 25, 2013
    Posts:
    5
  21. imboxmis

    imboxmis

    Joined:
    Feb 5, 2014
    Posts:
    1
    hi if i play it using mouse it will detect it or not? or should i need to build and run it and play it on phone to see if its working?
     
  22. hgaur725

    hgaur725

    Joined:
    Feb 20, 2014
    Posts:
    17
  23. Kaworuyoshi90

    Kaworuyoshi90

    Joined:
    Apr 23, 2013
    Posts:
    1
    Actually OnMouseDown detects when a GameObject with a collider is touched, without using raycanting, very basic stuff, cause only detects if it's touched or not, it doesn't tell you what finger or how many fingers are touching it.
     
  24. pfonseca

    pfonseca

    Joined:
    Aug 9, 2014
    Posts:
    1
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class SwipeScript : MonoBehaviour {
    4.     private float fingerStartTime  = 0.0f;
    5.     private Vector2 fingerStartPos = Vector2.zero;
    6.    
    7.     private bool isSwipe = false;
    8.     private float minSwipeDist  = 50.0f;
    9.     private float maxSwipeTime = 0.5f;
    10.    
    11.     // Update is called once per frame
    12.     void Update () {
    13.    
    14.         if (Input.touchCount > 0){
    15.             foreach (Touch touch in Input.touches)
    16.             {
    17.                 switch (touch.phase)
    18.                 {
    19.                 case TouchPhase.Began :
    20.                     /* this is a new touch */
    21.                     isSwipe = true;
    22.                     fingerStartTime = Time.time;
    23.                     fingerStartPos = touch.position;
    24.                     break;
    25.                    
    26.                 case TouchPhase.Canceled :
    27.                     /* The touch is being canceled */
    28.                     isSwipe = false;
    29.                     break;
    30.                    
    31.                 case TouchPhase.Ended :
    32.                     float gestureTime = Time.time - fingerStartTime;
    33.                     float gestureDist = (touch.position - fingerStartPos).magnitude;
    34.                        
    35.                     if (isSwipe && gestureTime < maxSwipeTime && gestureDist > minSwipeDist){
    36.                         Vector2 direction = touch.position - fingerStartPos;
    37.                         Vector2 swipeType = Vector2.zero;
    38.                        
    39.                         if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y)){
    40.                             // the swipe is horizontal:
    41.                             swipeType = Vector2.right * Mathf.Sign(direction.x);
    42.                         }else{
    43.                             // the swipe is vertical:
    44.                             swipeType = Vector2.up * Mathf.Sign(direction.y);
    45.                         }
    46.                         if(swipeType.x != 0.0f){
    47.                             if(swipeType.x > 0.0f){
    48.                                 // MOVE RIGHT
    49.                             }else{
    50.                                 // MOVE LEFT
    51.                             }
    52.                         }
    53.                         if(swipeType.y != 0.0f ){
    54.                             if(swipeType.y > 0.0f){
    55.                                 // MOVE UP
    56.                             }else{
    57.                                 // MOVE DOWN
    58.                             }
    59.                         }
    60.                     }
    61.                        
    62.                     break;
    63.                 }
    64.             }
    65.         }
    66.     }
    67. }

    http://pfonseca.com/swipe-detection-on-unity/
     
  25. naka88sushi_

    naka88sushi_

    Joined:
    May 8, 2014
    Posts:
    2
    excuse me, but will this code work on windows phone too?
     
  26. DeveshPandey

    DeveshPandey

    Joined:
    Sep 30, 2012
    Posts:
    221
  27. bendprogrammer

    bendprogrammer

    Joined:
    Apr 7, 2014
    Posts:
    5
    it's old but really helps,
    thx.