Detect swipe without losing immediate response of tap












0















I'm creating an Android game with Unity. There are only three ways to control the movement of the character:




  • Tap in the right half of the screen: jump to the right

  • Tap in the left half of the screen: jump to the left

  • Swipe upwards: character dashes forward


In theory, I know that I can differentiate the touches with the TouchPhases (began, moved, stationary and ended). When only detecting the taps without caring for swipes, I just checked if the phase of the touch began and made the player jump. That felt fast on my device.



However, because I have to consider that a swipe may follow, I can not initiate the jump action until I detected ThouchPhase.Ended. This leads to a very slow responding character, which doesnt jump until the user rises his finger of the screen.



I tried to use ThouchPhase.Moved and ThouchPhase.Stationary instead to simulate a immediate response but my solution is pretty bad in terms of detecting the difference between a tap and a swipe:



Vector2 startTouchPosition;
Vector2 endTouchPosition;
Vector2 currentSwipe;

void Update()
{
if (Input.touches.Length > 0)
{
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);

if (touch.phase == TouchPhase.Began)
{
//save began touch 2d point
startTouchPosition = new Vector2(touch.position.x, touch.position.y);
}

if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
{
//save ended touch 2d point
endTouchPosition = new Vector2(touch.position.x, touch.position.y);

if (endTouchPosition.y - startTouchPosition.y < 5)
{
if (touch.position.x > (Screen.width / 2))
{
JumpToRight();
}
else if (touch.position.x < (Screen.width / 2))
{
JumpToLeft();
}
}
else
{
//create vector from the two points
currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

//normalize the 2d vector
currentSwipe.Normalize();

//swipe upwards
if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
DashForward();
}
}
}
}
}
}









share|improve this question

























  • I was trying to implement something similar. I think you need the stationary case || with the began case. And put moved case || end together. Let me know if it works.

    – Aykut Karaca
    Jan 18 at 21:59













  • Unfortunatly I cant figure it out.. I set the startPosition in the began phase and jumped when phase was stationary. When the phase ended or moved, I checked if the distance between start- and endposition is greater a minimum distance and then executed the dash. Its still not reliable because the swipe sometimes seems to have a stationary phase in the beginning. then the player just jumps instead dashing.

    – h4nk
    Jan 20 at 7:55
















0















I'm creating an Android game with Unity. There are only three ways to control the movement of the character:




  • Tap in the right half of the screen: jump to the right

  • Tap in the left half of the screen: jump to the left

  • Swipe upwards: character dashes forward


In theory, I know that I can differentiate the touches with the TouchPhases (began, moved, stationary and ended). When only detecting the taps without caring for swipes, I just checked if the phase of the touch began and made the player jump. That felt fast on my device.



However, because I have to consider that a swipe may follow, I can not initiate the jump action until I detected ThouchPhase.Ended. This leads to a very slow responding character, which doesnt jump until the user rises his finger of the screen.



I tried to use ThouchPhase.Moved and ThouchPhase.Stationary instead to simulate a immediate response but my solution is pretty bad in terms of detecting the difference between a tap and a swipe:



Vector2 startTouchPosition;
Vector2 endTouchPosition;
Vector2 currentSwipe;

void Update()
{
if (Input.touches.Length > 0)
{
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);

if (touch.phase == TouchPhase.Began)
{
//save began touch 2d point
startTouchPosition = new Vector2(touch.position.x, touch.position.y);
}

if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
{
//save ended touch 2d point
endTouchPosition = new Vector2(touch.position.x, touch.position.y);

if (endTouchPosition.y - startTouchPosition.y < 5)
{
if (touch.position.x > (Screen.width / 2))
{
JumpToRight();
}
else if (touch.position.x < (Screen.width / 2))
{
JumpToLeft();
}
}
else
{
//create vector from the two points
currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

//normalize the 2d vector
currentSwipe.Normalize();

//swipe upwards
if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
DashForward();
}
}
}
}
}
}









share|improve this question

























  • I was trying to implement something similar. I think you need the stationary case || with the began case. And put moved case || end together. Let me know if it works.

    – Aykut Karaca
    Jan 18 at 21:59













  • Unfortunatly I cant figure it out.. I set the startPosition in the began phase and jumped when phase was stationary. When the phase ended or moved, I checked if the distance between start- and endposition is greater a minimum distance and then executed the dash. Its still not reliable because the swipe sometimes seems to have a stationary phase in the beginning. then the player just jumps instead dashing.

    – h4nk
    Jan 20 at 7:55














0












0








0








I'm creating an Android game with Unity. There are only three ways to control the movement of the character:




  • Tap in the right half of the screen: jump to the right

  • Tap in the left half of the screen: jump to the left

  • Swipe upwards: character dashes forward


In theory, I know that I can differentiate the touches with the TouchPhases (began, moved, stationary and ended). When only detecting the taps without caring for swipes, I just checked if the phase of the touch began and made the player jump. That felt fast on my device.



However, because I have to consider that a swipe may follow, I can not initiate the jump action until I detected ThouchPhase.Ended. This leads to a very slow responding character, which doesnt jump until the user rises his finger of the screen.



I tried to use ThouchPhase.Moved and ThouchPhase.Stationary instead to simulate a immediate response but my solution is pretty bad in terms of detecting the difference between a tap and a swipe:



Vector2 startTouchPosition;
Vector2 endTouchPosition;
Vector2 currentSwipe;

void Update()
{
if (Input.touches.Length > 0)
{
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);

if (touch.phase == TouchPhase.Began)
{
//save began touch 2d point
startTouchPosition = new Vector2(touch.position.x, touch.position.y);
}

if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
{
//save ended touch 2d point
endTouchPosition = new Vector2(touch.position.x, touch.position.y);

if (endTouchPosition.y - startTouchPosition.y < 5)
{
if (touch.position.x > (Screen.width / 2))
{
JumpToRight();
}
else if (touch.position.x < (Screen.width / 2))
{
JumpToLeft();
}
}
else
{
//create vector from the two points
currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

//normalize the 2d vector
currentSwipe.Normalize();

//swipe upwards
if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
DashForward();
}
}
}
}
}
}









share|improve this question
















I'm creating an Android game with Unity. There are only three ways to control the movement of the character:




  • Tap in the right half of the screen: jump to the right

  • Tap in the left half of the screen: jump to the left

  • Swipe upwards: character dashes forward


In theory, I know that I can differentiate the touches with the TouchPhases (began, moved, stationary and ended). When only detecting the taps without caring for swipes, I just checked if the phase of the touch began and made the player jump. That felt fast on my device.



However, because I have to consider that a swipe may follow, I can not initiate the jump action until I detected ThouchPhase.Ended. This leads to a very slow responding character, which doesnt jump until the user rises his finger of the screen.



I tried to use ThouchPhase.Moved and ThouchPhase.Stationary instead to simulate a immediate response but my solution is pretty bad in terms of detecting the difference between a tap and a swipe:



Vector2 startTouchPosition;
Vector2 endTouchPosition;
Vector2 currentSwipe;

void Update()
{
if (Input.touches.Length > 0)
{
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);

if (touch.phase == TouchPhase.Began)
{
//save began touch 2d point
startTouchPosition = new Vector2(touch.position.x, touch.position.y);
}

if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
{
//save ended touch 2d point
endTouchPosition = new Vector2(touch.position.x, touch.position.y);

if (endTouchPosition.y - startTouchPosition.y < 5)
{
if (touch.position.x > (Screen.width / 2))
{
JumpToRight();
}
else if (touch.position.x < (Screen.width / 2))
{
JumpToLeft();
}
}
else
{
//create vector from the two points
currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

//normalize the 2d vector
currentSwipe.Normalize();

//swipe upwards
if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
DashForward();
}
}
}
}
}
}






android unity3d gesture






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 18 at 16:08









Robert Harvey

148k33274417




148k33274417










asked Jan 18 at 16:07









h4nkh4nk

51




51













  • I was trying to implement something similar. I think you need the stationary case || with the began case. And put moved case || end together. Let me know if it works.

    – Aykut Karaca
    Jan 18 at 21:59













  • Unfortunatly I cant figure it out.. I set the startPosition in the began phase and jumped when phase was stationary. When the phase ended or moved, I checked if the distance between start- and endposition is greater a minimum distance and then executed the dash. Its still not reliable because the swipe sometimes seems to have a stationary phase in the beginning. then the player just jumps instead dashing.

    – h4nk
    Jan 20 at 7:55



















  • I was trying to implement something similar. I think you need the stationary case || with the began case. And put moved case || end together. Let me know if it works.

    – Aykut Karaca
    Jan 18 at 21:59













  • Unfortunatly I cant figure it out.. I set the startPosition in the began phase and jumped when phase was stationary. When the phase ended or moved, I checked if the distance between start- and endposition is greater a minimum distance and then executed the dash. Its still not reliable because the swipe sometimes seems to have a stationary phase in the beginning. then the player just jumps instead dashing.

    – h4nk
    Jan 20 at 7:55

















I was trying to implement something similar. I think you need the stationary case || with the began case. And put moved case || end together. Let me know if it works.

– Aykut Karaca
Jan 18 at 21:59







I was trying to implement something similar. I think you need the stationary case || with the began case. And put moved case || end together. Let me know if it works.

– Aykut Karaca
Jan 18 at 21:59















Unfortunatly I cant figure it out.. I set the startPosition in the began phase and jumped when phase was stationary. When the phase ended or moved, I checked if the distance between start- and endposition is greater a minimum distance and then executed the dash. Its still not reliable because the swipe sometimes seems to have a stationary phase in the beginning. then the player just jumps instead dashing.

– h4nk
Jan 20 at 7:55





Unfortunatly I cant figure it out.. I set the startPosition in the began phase and jumped when phase was stationary. When the phase ended or moved, I checked if the distance between start- and endposition is greater a minimum distance and then executed the dash. Its still not reliable because the swipe sometimes seems to have a stationary phase in the beginning. then the player just jumps instead dashing.

– h4nk
Jan 20 at 7:55












1 Answer
1






active

oldest

votes


















0














Here is the code I used. I tested and it works but sometimes, I noted a delay. Let me know if it is good enough for you. Basically you dont need to go through all touches if you dont need multi-touch. And you just need Begin and End touch phases.



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

public class touch : MonoBehaviour {
private Vector2 startTouchPosition;
private Vector2 endTouchPosition;
private Vector2 currentSwipe;
public Text textbox;
// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
if (Input.touches.Length > 0)
{

Touch touch = Input.GetTouch(0);

if (touch.phase == TouchPhase.Began)
{
//save began touch 2d point
startTouchPosition = new Vector2(touch.position.x, touch.position.y);
}

if (touch.phase == TouchPhase.Ended)
{
//save ended touch 2d point
endTouchPosition = new Vector2(touch.position.x, touch.position.y);
//create vector from the two points
currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

//normalize the 2d vector
currentSwipe.Normalize();
if(Mathf.Abs(currentSwipe.y) < 0.1f && Mathf.Abs(currentSwipe.x) < 0.1f)
{
if (touch.position.x > (Screen.width / 2))
{
textbox.text= "jump right";
}
else if (touch.position.x < (Screen.width / 2))
{
textbox.text= "jump left";

}
}
if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
textbox.text= "Dash forward";

}
}
}
}
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54257582%2fdetect-swipe-without-losing-immediate-response-of-tap%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    Here is the code I used. I tested and it works but sometimes, I noted a delay. Let me know if it is good enough for you. Basically you dont need to go through all touches if you dont need multi-touch. And you just need Begin and End touch phases.



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

    public class touch : MonoBehaviour {
    private Vector2 startTouchPosition;
    private Vector2 endTouchPosition;
    private Vector2 currentSwipe;
    public Text textbox;
    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
    if (Input.touches.Length > 0)
    {

    Touch touch = Input.GetTouch(0);

    if (touch.phase == TouchPhase.Began)
    {
    //save began touch 2d point
    startTouchPosition = new Vector2(touch.position.x, touch.position.y);
    }

    if (touch.phase == TouchPhase.Ended)
    {
    //save ended touch 2d point
    endTouchPosition = new Vector2(touch.position.x, touch.position.y);
    //create vector from the two points
    currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

    //normalize the 2d vector
    currentSwipe.Normalize();
    if(Mathf.Abs(currentSwipe.y) < 0.1f && Mathf.Abs(currentSwipe.x) < 0.1f)
    {
    if (touch.position.x > (Screen.width / 2))
    {
    textbox.text= "jump right";
    }
    else if (touch.position.x < (Screen.width / 2))
    {
    textbox.text= "jump left";

    }
    }
    if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
    {
    textbox.text= "Dash forward";

    }
    }
    }
    }
    }





    share|improve this answer




























      0














      Here is the code I used. I tested and it works but sometimes, I noted a delay. Let me know if it is good enough for you. Basically you dont need to go through all touches if you dont need multi-touch. And you just need Begin and End touch phases.



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

      public class touch : MonoBehaviour {
      private Vector2 startTouchPosition;
      private Vector2 endTouchPosition;
      private Vector2 currentSwipe;
      public Text textbox;
      // Use this for initialization
      void Start () {

      }

      // Update is called once per frame
      void Update () {
      if (Input.touches.Length > 0)
      {

      Touch touch = Input.GetTouch(0);

      if (touch.phase == TouchPhase.Began)
      {
      //save began touch 2d point
      startTouchPosition = new Vector2(touch.position.x, touch.position.y);
      }

      if (touch.phase == TouchPhase.Ended)
      {
      //save ended touch 2d point
      endTouchPosition = new Vector2(touch.position.x, touch.position.y);
      //create vector from the two points
      currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

      //normalize the 2d vector
      currentSwipe.Normalize();
      if(Mathf.Abs(currentSwipe.y) < 0.1f && Mathf.Abs(currentSwipe.x) < 0.1f)
      {
      if (touch.position.x > (Screen.width / 2))
      {
      textbox.text= "jump right";
      }
      else if (touch.position.x < (Screen.width / 2))
      {
      textbox.text= "jump left";

      }
      }
      if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
      {
      textbox.text= "Dash forward";

      }
      }
      }
      }
      }





      share|improve this answer


























        0












        0








        0







        Here is the code I used. I tested and it works but sometimes, I noted a delay. Let me know if it is good enough for you. Basically you dont need to go through all touches if you dont need multi-touch. And you just need Begin and End touch phases.



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

        public class touch : MonoBehaviour {
        private Vector2 startTouchPosition;
        private Vector2 endTouchPosition;
        private Vector2 currentSwipe;
        public Text textbox;
        // Use this for initialization
        void Start () {

        }

        // Update is called once per frame
        void Update () {
        if (Input.touches.Length > 0)
        {

        Touch touch = Input.GetTouch(0);

        if (touch.phase == TouchPhase.Began)
        {
        //save began touch 2d point
        startTouchPosition = new Vector2(touch.position.x, touch.position.y);
        }

        if (touch.phase == TouchPhase.Ended)
        {
        //save ended touch 2d point
        endTouchPosition = new Vector2(touch.position.x, touch.position.y);
        //create vector from the two points
        currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

        //normalize the 2d vector
        currentSwipe.Normalize();
        if(Mathf.Abs(currentSwipe.y) < 0.1f && Mathf.Abs(currentSwipe.x) < 0.1f)
        {
        if (touch.position.x > (Screen.width / 2))
        {
        textbox.text= "jump right";
        }
        else if (touch.position.x < (Screen.width / 2))
        {
        textbox.text= "jump left";

        }
        }
        if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
        {
        textbox.text= "Dash forward";

        }
        }
        }
        }
        }





        share|improve this answer













        Here is the code I used. I tested and it works but sometimes, I noted a delay. Let me know if it is good enough for you. Basically you dont need to go through all touches if you dont need multi-touch. And you just need Begin and End touch phases.



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

        public class touch : MonoBehaviour {
        private Vector2 startTouchPosition;
        private Vector2 endTouchPosition;
        private Vector2 currentSwipe;
        public Text textbox;
        // Use this for initialization
        void Start () {

        }

        // Update is called once per frame
        void Update () {
        if (Input.touches.Length > 0)
        {

        Touch touch = Input.GetTouch(0);

        if (touch.phase == TouchPhase.Began)
        {
        //save began touch 2d point
        startTouchPosition = new Vector2(touch.position.x, touch.position.y);
        }

        if (touch.phase == TouchPhase.Ended)
        {
        //save ended touch 2d point
        endTouchPosition = new Vector2(touch.position.x, touch.position.y);
        //create vector from the two points
        currentSwipe = new Vector2(endTouchPosition.x - startTouchPosition.x, endTouchPosition.y - startTouchPosition.y);

        //normalize the 2d vector
        currentSwipe.Normalize();
        if(Mathf.Abs(currentSwipe.y) < 0.1f && Mathf.Abs(currentSwipe.x) < 0.1f)
        {
        if (touch.position.x > (Screen.width / 2))
        {
        textbox.text= "jump right";
        }
        else if (touch.position.x < (Screen.width / 2))
        {
        textbox.text= "jump left";

        }
        }
        if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
        {
        textbox.text= "Dash forward";

        }
        }
        }
        }
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 days ago









        Aykut KaracaAykut Karaca

        779




        779






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54257582%2fdetect-swipe-without-losing-immediate-response-of-tap%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Liquibase includeAll doesn't find base path

            How to use setInterval in EJS file?

            Petrus Granier-Deferre