Simple 2D drag & drop system

Hi all :slight_smile:

I would like to realize an android game where the user is supposed to drag a shape into the right spot (that has the same shop of the object). What’s the simplest way to achieve something like that? ty very much

Does this help?

1 Like

Hi, thx for the reply :slight_smile: do u think working with the ui system will be more simple of using sprites?

The new UI system is quite robust. You can easily have a spritesheet, and use the unity editor (setting sprite mode to multiple) to break it up into individual images, which you can then use with the UI Image or Button object. Just read up on the new UI system, and watch that video above.

ty so much! now I wonder if there is a way to load randomly ui object (let’s say I have 3 baloons of different color and I want at the begin of the level they load in 3 different spots everytime. is that achievable using the ui?

Yes.

Note that the solution in the video is not restricted to UI. It will work on sprites or even 3D objects with some tweaking.

I can’t understand what I’m doing wrong :confused:

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {

    public static GameObject itemBeingDragged;
    Vector3 startPosition;

    #region IBeginDragHandler implementation

    public void OnBeginDrag (PointerEventData eventData)
    {
        itemBeingDragged = gameObject;
        startPosition = transform.position;
    }

    #endregion

    #region IDragHandler implementation

    public void OnDrag (PointerEventData eventData)
    {
        transform.position = Input.mousePosition;
    }

    #endregion

    #region IEndDragHandler implementation

    public void OnEndDrag (PointerEventData eventData)
    {
        itemBeingDragged = null;
        transform.position = startPosition;
    }

    #endregion



}

I attach this to my 2dsprites but is not dragging nothing :confused: the problem is I’m using just 2sprites…not canvas…so maybe is this?

If you are using 2D sprites you need the following

  • Event System game object somewhere in the scene (Easiest way to get this is to make a canvas, then delete the canvas)
  • Collider2D on each of the sprites. (A Rigidbody2D is also advisable if the sprites are to move)
  • A Physics2d Raycaster on the appropriate camera

thx for your interest. I’ll try that later…at the moment I’m using the new ui system. now I’m strugglin with the lerp thingy…what’s wrong with this code?

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {

    public static GameObject itemBeingDragged;
    Vector3 startPosition;

    #region IBeginDragHandler implementation

    public void OnBeginDrag (PointerEventData eventData)
    {
        itemBeingDragged = gameObject;
        startPosition = transform.position;
    }

    #endregion

    #region IDragHandler implementation

    public void OnDrag (PointerEventData eventData)
    {
        transform.position = Input.mousePosition;
    }

    #endregion

    #region IEndDragHandler implementation

    public void OnEndDrag (PointerEventData eventData)
    {
        itemBeingDragged = null;
        transform.position = startPosition;
    }

    #endregion



}

I think it’s ok but when I stop drag the item stay in the last position where I stop the drag…

I’m sorry the lerp thingy is heretransform.position = Vector3.Lerp(Input.mousePosition, startPosition, Time.deltaTime);

I’m following the tutorial and I’m creating the slot for the drop…when I modify the drag script I get this error "there is no “canvasgroup” attached to the “item” gameobject but a script is trying to access it…I followed step by step…I post the code here.

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {

    public static GameObject itemBeingDragged;
    Vector3 startPosition;
    Transform startParent;


    #region IBeginDragHandler implementation

    public void OnBeginDrag (PointerEventData eventData)
    {
        itemBeingDragged = gameObject;
        startPosition = transform.position;
        startParent = transform.parent;
        GetComponent<CanvasGroup>().blocksRaycasts = false;
    }

    #endregion

    #region IDragHandler implementation

    public void OnDrag (PointerEventData eventData)
    {
        transform.position = Input.mousePosition;
    }

    #endregion

    #region IEndDragHandler implementation

    public void OnEndDrag (PointerEventData eventData)
    {
        itemBeingDragged = null;
        GetComponent<CanvasGroup>().blocksRaycasts = true;
        if(transform.parent != startParent)
       
        {
       
            transform.position = startPosition;
       
        }

    #endregion



}
}

is actually possible insert a lerp to make the object going back or I need an update function to do that?

hey boredmormon, I solved all. Now everything works…but I still have 2 questions, I hope you are so kind to answer me.

A) still the lerp thingy. I don’t want the object to just snap back in position, I would like to see the object actually going back on the start position.

B) there is a way to do some slots “exclusive” like a particular slot accept just a particular item? thx in advance

for the lerp thingy I did like this at the moment but is not working

if (transform.parent == startParent)
        {
            transform.position = Vector3.Lerp(transform.position, startPosition, Time.deltaTime);
        }

Lerp can’t be done in one frame, you have to call it over several frames. Here is one way to do it.

// ...
if (transform.parent == startParent) {
    StarCoroutine(LerpBackToStart());
}
// ...


void IEnumerator LerpBackToStart () {
    while ((transform.position - startPosition).sqrMagnitude > 0.01f){
        transform.position = Vector3.Lerp(transform.position, startPosition, Time.deltaTime);
        yield return null;
    }
    transform.position = startPosition;
}

Note that this is a misuse of Lerp and Time.deltaTime. But it does work after a fashion.

You also probably want to stop the coroutine if the user starts a new drag.

thanks I’ll try when I’ll get home :slight_smile: and for the exclusive slot do u have some suggestion?

I’m trying this solution for the lerp but the booleang going back always is true even if is set to false on the start void…dunno why…

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {

    public static GameObject itemBeingDragged;
    Vector3 startPosition;
    public float speed;
    public bool goingBack = false;
    Transform startParent;


    void Start (){
               
        goingBack = false;

    }

    void Update () {

   
        PositionChanging ();

    }

    void PositionChanging() {

        if (goingBack = true)
                {
                transform.position = Vector3.Lerp (transform.position, startPosition, Time.deltaTime * speed);
                }
   
    }




    #region IBeginDragHandler implementation

    public void OnBeginDrag (PointerEventData eventData)
    {

        itemBeingDragged = gameObject;
        startPosition = transform.position;
        startParent = transform.parent;
        GetComponent<CanvasGroup> ().blocksRaycasts = false;
    }

    #endregion

    #region IDragHandler implementation

    public void OnDrag (PointerEventData eventData)
    {
        transform.position = Input.mousePosition;
    }

    #endregion

    #region IEndDragHandler implementation

    public void OnEndDrag (PointerEventData eventData)
    {

        itemBeingDragged = null;
        GetComponent<CanvasGroup> ().blocksRaycasts = true;
        if (transform.parent == startParent)
        {
            goingBack = true;
        }
   
#endregion



    }
}

with your method I’m getting an error “unexpected symbol in LerpBackToStart” and “class,struct or interface method must have a return type”…

Let me do some playing on my PC when I get home tonight and I’ll get back to you.

U are a really good guy. I really appreciate that. thanks

Any luck with the lerp and the exclusive slot? :frowning: