- Home /
Dragging a 2D sprite with touch
Hi. I would like a red circle to be moved when the player touches it, as in a touch on an iPhone. and then drags the red circle somewhere. I would like the red circle to go wherever the user's finger goes. I am still fairly new to Unity so, I have no clue how to do this. Would anyone mind helping me out? Thanks!
Answer by Xarbrough · Jun 21, 2015 at 11:39 PM
There are many ways to achieve this, but I recommend the EventSystems DragHandler:
1) Make sure you create an EventSystem component in your hierarchy. 2) Add a Physics 2D Raycaster component to your Main Camera. 3) Write a script that implements IBeginDragHandler, IDragHandler and IEndDragHandler. 4) Add the script to the 2D sprite. Add a 2D Collider as well.
Here is a demo script how it could look. Be aware that the logic in this one might not fit, what you're doing:
using UnityEngine;
using UnityEngine.EventSystems;
public class DragAndDrop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public static GameObject DraggedInstance;
Vector3 _startPosition;
Vector3 _offsetToMouse;
float _zDistanceToCamera;
#region Interface Implementations
public void OnBeginDrag (PointerEventData eventData)
{
DraggedInstance = gameObject;
_startPosition = transform.position;
_zDistanceToCamera = Mathf.Abs (_startPosition.z - Camera.main.transform.position.z);
_offsetToMouse = _startPosition - Camera.main.ScreenToWorldPoint (
new Vector3 (Input.mousePosition.x, Input.mousePosition.y, _zDistanceToCamera)
);
}
public void OnDrag (PointerEventData eventData)
{
if(Input.touchCount > 1)
return;
transform.position = Camera.main.ScreenToWorldPoint (
new Vector3 (Input.mousePosition.x, Input.mousePosition.y, _zDistanceToCamera)
) + _offsetToMouse;
}
public void OnEndDrag (PointerEventData eventData)
{
DraggedInstance = null;
_offsetToMouse = Vector3.zero;
}
#endregion
}
There are other ways, like raycasting from the camera into the scene and figuring out what was hit, but honestly I think Unity has a pretty good built-in solution which is much less error prone once you get it working.
@Xarbrough Thank you so much, but I think I didn't make it clear it the question that I am trying to make it so when the user touches, as in on an iPhone, a red circle and drags it the circle will move with the user's finger.
$$anonymous$$y script should do that or at least get you started in the right direction. If you set up everything as described, when you touch or click (Input.mousePosition will also be called by a single touch) the object which this script is attached to, will move.
Thank you, very clear and simple pointers. Love the way it uses the event system.
Answer by PsyKzz · Nov 22, 2016 at 09:05 AM
Expanding a little on @chrismkhill. The issue with his implementation was if you moved the mouse too fast, you'd lose the sprite
The following would fix that.
Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
bool overSprite = GetComponent<SpriteRenderer>().bounds.Contains(mousePosition);
beingDragged = beingDragged && Input.GetButton("Fire1");
if (overSprite)
{
//If we've pressed down on the mouse (or touched on the iphone)
if (Input.GetButton("Fire1"))
{
beingDragged = true;
}
}
if (beingDragged) {
//Set the position to the mouse position
transform.position = new Vector3(Camera.main.ScreenToWorldPoint(Input.mousePosition).x,
Camera.main.ScreenToWorldPoint(Input.mousePosition).y,
0.0f);
}
This bug also appearing in IDragHandler interface,so to preserve from this;your solution working quite nice.Removed DragHandler while keeping IDropHandler to end pointer follow,I used On$$anonymous$$ouseDrag method.It works both pc and mobile.
Please, I don't understand why this happens, what did you do, please explain to me
I see a double confirmation, it works, but I would like to know why ...
Answer by chrismkhill · Jun 22, 2015 at 07:13 AM
Hey there,
If you create a script with this code on a sprite, you should get what you want.
// Update is called once per frame
void Update ()
{
//Gets the world position of the mouse on the screen
Vector2 mousePosition = Camera.main.ScreenToWorldPoint( Input.mousePosition );
//Checks whether the mouse is over the sprite
bool overSprite = this.GetComponent<SpriteRenderer>().bounds.Contains( mousePosition );
//If it's over the sprite
if (overSprite)
{
//If we've pressed down on the mouse (or touched on the iphone)
if (Input.GetButton("Fire1"))
{
//Set the position to the mouse position
this.transform.position = new Vector3(Camera.main.ScreenToWorldPoint(Input.mousePosition).x,
Camera.main.ScreenToWorldPoint(Input.mousePosition).y,
0.0f);
}
}
}