0
votes

I am trying make a functionality to my game so that the object with containerTransform can move 720f left or right depending upon the touch inputs. I have used Vector3.MoveTowards() but, it shows a **glitchy back and forth movement whenever I swipe right or left, instead of proper transition 720f right or left. I am not sure where my logic went wrong. Here are the complete codes. I am seeking your help. Thank you

private Vector2 startPosition;
private Vector2 endPosition;

public Transform containerTransform;
public float speed;
public float SoftZone = 20f;
//soft zone is the distance upto which the swipe wont work, so swipe length less than it wont trigger the function;

private bool SwipeLeft;
private bool SwipeRight;
private bool boolean;

private Vector3 currentLocation;
private Vector3 endLocation;

void Start()
{
    currentLocation = containerTransform.position;
    endLocation = containerTransform.position;
}


void Update()
{

    if(SwipeLeft) {

        containerTransform.position = Vector3.MoveTowards(

            currentLocation, 
            endLocation,
            Time.deltaTime * speed
            );

        if(containerTransform.position == endLocation) {

            SwipeLeft = false;
            currentLocation = endLocation;

            print("swipeleft ends");
        }
    }

    if(SwipeRight) {

        containerTransform.position = Vector3.MoveTowards(

            currentLocation, 
            endLocation,
            Time.deltaTime * speed
            );

        if(containerTransform.position == endLocation) {

            SwipeRight = false;
            currentLocation = endLocation;

            print("swiperight ends");
        }
    }

    SwipeCheck ();
}

void SwipeCheck () {

    /*if (!SwipeConfirmed){*/

 foreach (Touch touch in Input.touches)
    {
        if(touch.phase == TouchPhase.Began)
        {
            startPosition = touch.position;
            endPosition = touch.position;

            boolean = true;
        }

        if (touch.phase == TouchPhase.Moved)
        {
            endPosition = touch.position;
        }

        if (touch.phase == TouchPhase.Ended ||
            touch.phase == TouchPhase.Canceled &&
            boolean == true)
        {
            if (startPosition.x - endPosition.x >= SoftZone)
            {

                SwipeLeft = true;
                print("left");

                endLocation += new Vector3(

                    endLocation.x - 720f, 
                    endLocation.y, 
                    endLocation.z
                );

            }
            else if(startPosition.x - endPosition.x <= -SoftZone)
            {   

                SwipeRight = true;
                print("right");

                endLocation += new Vector3(

                    endLocation.x + 720f, 
                    endLocation.y, 
                    endLocation.z
                );
                boolean = false;
            }
        }
    }
}
1
Are you having an issue with MoveTowards or with getting the Vector3 from your swipe logic? A Minimal, Complete, and Verifiable would help here determining where your issue really is. I suggest code with debug statements showing your calculations and then copy-paste the output like code in your question.Eliasar

1 Answers

1
votes

First of all, Touch.position gives you

The position of the touch in pixel coordinates.

In order to use them for transform.position, you have to convert them to world space 3D coordinates using Camera.ScreenToWorldPoint like

var worldPosition = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, distanceToCamera);

Where distanceToCamera is a value you have to define/calculate to determine how far the point should be in front of the camera.


Note

If you use this often as in Update, you should store the Camera and reuse the reference like this:

private Camera cam;

private void Awake ()
{
    cam = Camera.main;
}

//...

var worldPosition = cam.ScreenToWorldPoint( ... );

The main issue

You are using

Vector3.MoveTowards(currentLocation, endLocation, speed * Time.deltaTime);

This will always start a new movement from currentLocation so you never move more than one step/frame away from the currentLocation.

Instead, use the actual current position of the object

containerTransform.position = Vector3.MoveTowards(containerTransform.position, endPosition, speed * Time.deltaTime);

Your code, SwipeLeft and SwipeRight actually do the same thing, so you could just remove one of the blocks.

if (Swipe)
{
    containerTransform.position = Vector3.MoveTowards(containerTransform.position, endPosition, speed * Time.deltaTime);

    if (containerTransform.position == endLocation)
    {
        Swipe = false;
        currentLocation = endLocation;

        print("swipe ends");
    }
}

and only set Swipe = true;


However, I would recommend using Coroutines instead of doing stuff in Update since they are better to control using StartCoroutine and StopCoroutine and passing the value you in you don't need the local variables currentLocation and endLocation.

It could look like

// Makes sure only one scrolling process is running at a time
private bool isScrolling;

private IEnumerator MoveTo(Vector3 targetPosition)
{
    if (isScrolling) yield break;

    isScrolling = true;
    while (containerTransform.position != targetPosition)
    {
        containerTransform.position = Vector3.MoveTowards(containerTransform.position, endPosition, speed * Time.deltaTime);

        yield return null;
    }

    isScrolling = false;
    print("Swipe ends");
}

If you rather would like to swipe within a certain time regardless how far the distance is you could use Vector3.Lerp instead

public float swipeDuration;

private IEnumerator MoveTo(Vector3 targetPosition)
{
    if (isScrolling) yield break;

    isScrolling = true;

    var currentPosition = containerTransform.position;

    var timePassed = 0.0f;

    while (timePassed < swipeDuration)
    {
        var lerpFactor = timePassed / swipeDuration;

        containerTransform.position = Vector3.Lerp(currentPosition, endPosition, lerpFactor);

        yield return null;
    }

    // To be sure set a fixed end position
    containerTransform.position = endPosition;

    isScrolling = false;
    print("Swipe ends");
}

Adobt your code in SwipeCheck() to use the new coroutine.

StartCoroutine (MoveTo(endLocationWorldPoint));