OleksandrYa
OleksandrYa

Reputation: 103

Unity3d Touch Swipe

If a player touch he jump and on swipe (left - right simply moves from left to right .. like any runner). Everything seems good but as always there is a BUT Here's the code:

Vector3 startPos;
float minSwipeDistX, minSwipeDistY;
bool isJump = false;

void Start()
{
    minSwipeDistX = minSwipeDistY = Screen.width / 6;
}

bool isSwipe = false;
bool isTouch = false;
void Update()
{
    if (Input.touchCount > 0)
    {
        Touch touch = Input.touches[0];
        switch (touch.phase)
        {
            case TouchPhase.Began:
                startPos = touch.position;
                break;
            case TouchPhase.Moved:
                isTouch = true;
                float swipeDistHorizontal = (new Vector3(touch.position.x, 0, 0) - new Vector3(startPos.x, 0, 0)).magnitude;
                float swipeDistVertical = (new Vector3(0, touch.position.y, 0) - new Vector3(0, startPos.y, 0)).magnitude;
                if (swipeDistHorizontal > minSwipeDistX)
                {
                    float swipeValue = Mathf.Sign(touch.position.x - startPos.x);
                    if (swipeValue > 0 && !isSwipe)//to right swipe
                    {
                        isTouch = false;
                        isSwipe = true;
                        Debug.Log("Right");
                    }
                    else if (swipeValue < 0 && !isSwipe)//to left swipe
                    {
                        isTouch = false;
                        isSwipe = true;
                        Debug.Log("Left");
                    }
                }
                // add swipe to up
                if (swipeDistVertical > minSwipeDistY)
                {
                    float swipeValueY = Mathf.Sign(touch.position.y - startPos.y);
                    if (swipeValueY > 0 && !isSwipe)
                    {
                        isTouch = false;
                        isSwipe = true;
                        Debug.Log("Up");
                    }
                }
                break;
            case TouchPhase.Stationary:
                isJump = true;
                break;
            case TouchPhase.Ended:
            case TouchPhase.Canceled:
                isTouch = false;
                isSwipe = false;
                break;
        }
    }
}

void FixedUpdate()
{
    if (isJump && !isTouch)
    {
        Debug.Log("Tap");
        isJump = false;
    }
}

When doing a simple touch (TouchPhase.Stationary) immediately reacts to the player jump. And when do Jump Swipe UP then jump player when I let go of the finger. I understand it all through what I use (TouchPhase.Ended). I tried to put TouchPhase.Moved but then all the time before the motion and use jump (TouchPhase.Stationary). Mauger who faced such a problem? If so then tell me how to do so was to touch and swipe swipe touch.

Upvotes: 0

Views: 8050

Answers (2)

OleksandrYa
OleksandrYa

Reputation: 103

This my code:

void Update()
{
#if UNITY_ANDROID || UNITY_IPHONE
    if (Input.touchCount > 0)
    {
        Touch touch = Input.touches[0];

        switch (touch.phase)
        {
            case TouchPhase.Began:
                startPos = touch.position;
                StartCoroutine(Jump());
                break;
            case TouchPhase.Moved:
                isSwipe = true;
                float swipeDistHorizontal = (new Vector3(touch.position.x, 0, 0) - new Vector3(startPos.x, 0, 0)).magnitude;
                float swipeDistVertical = (new Vector3(0, touch.position.y, 0) - new Vector3(0, startPos.y, 0)).magnitude;
                if (swipeDistHorizontal > minSwipeDistX)
                {
                    float swipeValue = Mathf.Sign(touch.position.x - startPos.x);
                    if (swipeValue > 0 && !isTouch)//to right swipe
                    {
                        isTouch = true;
                        StartCoroutine(Right());
                    }
                    else if (swipeValue < 0 && !isTouch)//to left swipe
                    {
                        isTouch = true;
                        StartCoroutine(Left());
                    }
                }

                //add swipe to up
                if(swipeDistVertical > minSwipeDistY)
                {
                    float swipeValue = Mathf.Sign(touch.position.y - startPos.y);
                    if(swipeValue > 0 && !isTouch)
                    {
                        isTouch = true;
                        StartCoroutine(Jump2());
                    }
                }
                break;
            case TouchPhase.Ended:
                isSwipe = false;
                isTouch = false;
                break;
        }
    }
    #endif
}
IEnumerator Jump2()
{
    yield return new WaitForSeconds(0.05f);
    if(playerVelocity <= 0.2f)
    {
        Debug.Log("Swipe Up");
    }
}

IEnumerator Jump()
{
    if (!isSwipe)
    {
        yield return new WaitForSeconds(0.05f);
        if (!isSwipe && playerVelocity <= 0.2f)
        {
            Debug.Log("Tap");

        }
        else
        {
            yield break;
        }
    }
    else
    {
        yield break;
    }
}

IEnumerator Right()
{
    Debug.Log("Right");

}

IEnumerator Left()
{
    Debug.Log("Left");

}

Upvotes: 1

G&#233;ry Arduino
G&#233;ry Arduino

Reputation: 490

I came up with that :

It should put you in the proper direction

    float validInputThresold = 5f;

enum Gestures {
    None,
    Stationary,
    SwipeRight,
    SwipeLeft,
    SwipeUp,
    SwipeDown
}

Gestures currentGesture;

public void Update() {
    currentGesture = Gestures.None;
    HandleTouch(Input.GetTouch(0));
    HandleCharacterMovement(currentGesture);
}

Vector3 originalPosition;
void HandleTouch(Touch touch) {
    if (touch == null) return;



    switch (touch.phase) {
        case TouchPhase.Began:
            originalPosition = touch.position;
            break;
        case TouchPhase.Moved:
            Vector3 delta = touch.position - originalPosition;
            if (delta.magnitude > validInputThresold) Moved(touch, delta);
            break;
        case TouchPhase.Stationary:
            currentGesture = Gestures.Stationary;
            break;
        case TouchPhase.Ended:
        case TouchPhase.Canceled:
            currentGesture = Gestures.None;
            break;
    }
}

public float gestureThresold = 10f;

void Moved(Touch touch, Vector3 delta) {
    if ((Mathf.Abs(delta.x)<=gestureThresold && Mathf.Abs(delta.y)<=gestureThresold)
        || (Mathf.Abs(delta.x)>gestureThresold && Mathf.Abs(delta.y)>gestureThresold) )
            currentGesture = Gestures.Stationary; //IF FINGER MOVED IN DIAGONAL, INVALID STATE FALLSBACK TO STATIONARY
    else if (delta.x > gestureThresold) currentGesture = Gestures.SwipeRight;
    else if (delta.x < -gestureThresold) currentGesture = Gestures.SwipeLeft;
    else if (delta.y > gestureThresold) currentGesture = Gestures.SwipeUp;
    else if (delta.y < -gestureThresold) currentGesture = Gestures.SwipeDown;
}


bool playerIsMoving = false;

// ALL THE ROUTINES HERE SET THE PLAYER IS MOVING FLAG
// TO TRUE AND THEN TO FALSE WHEN THE MOVEMENT IS DONE
void HandleCharacterMovement(Gestures gesture) {
    if (playerIsMoving) return;

    switch (gesture) {

        default:
        case Gestures.None:
        case Gestures.Stationary:
            return;

        case Gestures.SwipeRight:
            StartCoroutine(MovePlayerRight());
            return;
        case Gestures.SwipeLeft:
            StartCoroutine(MovePlayerLeft());
            return;
        case Gestures.SwipeUp:
            StartCoroutine(Jump());
            return;
        case Gestures.SwipeDown:
            StartCoroutine(Crouch());
            return;
    }
}

Not sure it is valid, did it by head. feel free to correct it.

The idea behind that :

  • Find the finger
  • If any and it is moving get the delta
  • if delta is over certain amount validate it
  • if valid assign a gesture state that you can track
  • process player movement accordingly if player is not already moving

Upvotes: 0

Related Questions