[SOLVED-ish] Jump to Touch Location, then Drag [ Mobile / 2D / C# ]

Goal: When the player drags a finger across the screen, the Swiper gameobject should appear at the initial touch location, then follow the finger (a child object of Swiper renders a collider trail behind it). (Single camera, 2D game for mobile phones). If the screen is not being touched, Swiper does nothing & is invisible.

Currently: I can make the Swiper jump to the touch location, but then I can’t get the drag to work OR the drag works, but the Swiper object stays where it’s at relative to the player’s finger and/or goes off screen. (Note that this is only a problem with the touch controls. If I drag the object with a mouse in the Unity Scene view, it works fine).

The current iteration of this script is based on this video:

The code:

using UnityEngine;
using System.Collections;

public class SwipeController : MonoBehaviour {

    float dragSpeed = 0.1f;

    float maxX = Screen.width;
    float minX = 0.0f;
    float maxY = Screen.height;
    float minY = 0.0f;

    Transform cachedTransform;

    void Start(){

        cachedTransform = transform;
        Debug.Log("Screen X: " + maxX.ToString() + ", Y: " + maxY.ToString()); // 'droid resolution 480 x 320
    }

    void Update(){

        if(Input.touchCount > 0)
        {
            Vector2 deltaPosition = Input.GetTouch(0).position;

           
            switch(Input.GetTouch(0).phase)
            {
                case TouchPhase.Began:
                    this.transform.position = deltaPosition;
                    Debug.Log("GT X: " + Input.GetTouch(0).position.x + ", Y: " + Input.GetTouch(0).position.y); // GetTouch position
                    Debug.Log("dP X: " + deltaPosition.x +", Y: " + deltaPosition.y);                            // deltaPosition
                    Debug.Log ("cT X: " + cachedTransform.position.x + ", Y: " + cachedTransform.position.y);    // cachedTransform position
                    break;
                case TouchPhase.Moved:
                    DragObject(deltaPosition);
                    break;
                case TouchPhase.Ended:
                    break;
            }

        }

    }

    void DragObject(Vector2 deltaPosition){
        cachedTransform.position = new Vector2(
            Mathf.Clamp((deltaPosition.x * dragSpeed) + cachedTransform.position.x, minX, maxX),
            Mathf.Clamp((deltaPosition.y * dragSpeed) + cachedTransform.position.y, minY, maxY)
            );
    }
   
}

Console output:

Any and all help is greatly appreciated.

Looks like all that was needed was to convert screen coordinates to world coordinates:

Vector2 pos;

    void Update(){
        MoveUpdate();
    }

    void MoveUpdate(){
        pos = Camera.main.ScreenToWorldPoint(new Vector2(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y));
        transform.position = new Vector2(pos.x, pos.y);
    }

This works the way it should, though it does generate an “Index out of bounds” error each frame.

You need to check if there are any touches. If there aren’t it will throw an “index out of bounds” exception when you call Input.GetTouch. Use Input.touchCount to check if there are any touches. See example below:

Vector2 pos;
void Update()
{
    if(Input.touchCount > 0)
    {
        MoveUpdate();
    }
}

void MoveUpdate()
{
    pos = Camera.main.ScreenToWorldPoint(new Vector2(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y));
    transform.position = new Vector2(pos.x, pos.y);
}