Skip to content

Implement Drag and Drop Item in Unity

Implement Drag and Drop Item in Unity

In this tutorial, we will implement a drag and drop item functionality in Unity. We will drag a UI item and drop it to instantiate a prefab on a 3D scene.

Contact me

Find the GitHub repository of this tutorial at https://github.com/shamim-akhtar/drag-and-drop.

Click to try the WebGL version below. NOTE: The WebGL version might not work for mobile devices.

https://faramira.com/downloads/dragdrop/WebGL/

Click on the above image to run the demo in WebGL (if your browser supports it)

The Unity Project

  • Create a new Unity 3D project.

The Ground

  • Right-click on the Hierarchy window and add a plan. Name it Ground.
  • Create a folder in Assets and call it Resources. Create another folder in Resources and name it Textures. Download the checkerboard image and put it in the folder Assets/Resources/Textures. Drag and drop this image onto the ground.
  • Set the Ground’s scale to be 10, 1, 10
  • Double-click on the checkerboard material and open the material file. Set the tile factor to 10, 10 as shown below.
Checkerboard material for the ground
  • Add a Box Collider component to the ground.
  • The Ground’s Inspection should look like below.
Inspector view of the Ground game object

The Dummy Prefabs

Next, we will create some dummy prefabs to initialise by dragging and dropping UI items. We will associate each UI item with one such prefab so that when we drop the UI item, we instantiate the correct prefab associated with that UI item.

For our demo, we will create a cube, a sphere and a cylinder. Go ahead and carry out the following steps.

  • Right-click on the Hierarchy window and create a new empty game object. Name it ObjCube and reset the transform.
  • Select ObjCube and add a cube game object as shown below.
Add a cube game object.
  • Create a material and name it MatCube. Set a colour to the material by selecting the Albedo, as shown below.
  • Set this material to the Cube.
The material for the cube.
  • Create a folder in the Resources directory; name it Prefabs. Drag and drop ObjCube to the Prefabs folder, and make it a prefab.
  • Delete ObjCube from the Hierarchy.

Repeat the above steps for a Sphere and a Cylinder. You can create a different material for the Sphere and the Cylinder.

Your Prefabs folder should now have three prefabs.

  • ObjCube
  • ObjSphere
  • ObjCylinder

The Canvas and the UI Item

Next, we create the Canvas and the UI items that we will drag.

  • Right-click on the Hierarchy window and create a new Canvas. Make sure that we have the settings as shown in the diagram below.
Settings for the canvas
  • Select the canvas and add a new UI Panel. Name this Panel as CardsPanel. Set the CardPanel’s parameters as shown below.
The UP Panel parameters
  • Create three subpanels within this CardPanel. Name the first sub-panel as Card1, the second as Card2 and the third as Card3.
Position of Card1 Panel
Position of Card2 Panel
Position of Card3 Panel
  • To each of these sub-panels, add two sprites. Name them Inner and Outer.
Inner and Outer sprites in each sub-panel
  • Set the Outer sprite’s parameter as shown in the picture below.
The Outer sprite’s parameters.
  • Download the icon for the cube, the icon for the sphere and the icon for the cylinder. Put these images in the Textures folder. Convert them to 2D sprite type.
  • Select the Inner sprite for Card1 and then set the width and height to be 50, 50. Drag and drop icon_sphere as set as the sprite for the Inner (as shown below).
Set the width, height and the sprite for the Inner for Card1.
  • Similarly, for Card2 Inner, set the icon_cylinder and for Card3 Inner, set icon_cube.
  • Your UI should like the below picture.
This picture shows the final UI for our demonstration.
  • Select the Camera and set the transform values as below. These values will make the camera position and orientation a bit better for us to view the ground.
Set the camera position and orientation to these values for a better view of the scene.

The Drag UI Item Script

So far, we have only created our scene for testing the drag and drop of UI items to instantiate prefabs on the scene. We will now begin the necessary script for our main feature.

  • Go ahead and create a new C# script file named DragUIItem.
  • Double-click this file and open it in Visual Studio.
  • Make the following change to the class declaration.
public class DragUIItem : 
  MonoBehaviour, 
  IBeginDragHandler, 
  IDragHandler, 
  IEndDragHandler
{
}Code language: C# (cs)
  • We want to implement three interfaces for our drag and drop to work. These interfaces are IBeginDragHandler, IDragHandler, and IEndDragHandler.
  • Add the following variables to the class.
  [SerializeField]
  GameObject PrefabToInstantiate;

  [SerializeField]
  RectTransform UIDragElement;

  [SerializeField]
  RectTransform Canvas;

  private Vector2 mOriginalLocalPointerPosition;
  private Vector3 mOriginalPanelLocalPosition;
  private Vector2 mOriginalPosition;

Code language: C# (cs)
  • Line 2 from the above code stores the reference to the prefab that we want to instantiate.
  • The variable in line 4 holds the reference to the UI element that we will drag. The variable in line 6 contains the reference to the canvas.

The Start Method

In the Start method, we store the initial position of the draggable UI item.

  private void Start()
  {
    mOriginalPosition = UIDragElement.localPosition;
  }
Code language: C# (cs)

Implement Interface Functions

  • Next, we implement the interface functions. These are:
OnBeginDrag
  public void OnBeginDrag(PointerEventData data)
  {
    mOriginalPanelLocalPosition = UIDragElement.localPosition;
    RectTransformUtility.ScreenPointToLocalPointInRectangle(
      Canvas, 
      data.position, 
      data.pressEventCamera, 
      out mOriginalLocalPointerPosition);
  }
Code language: C# (cs)

OnDrag

  public void OnDrag(PointerEventData data)
  {
    Vector2 localPointerPosition;
    if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
      Canvas, 
      data.position, 
      data.pressEventCamera, 
      out localPointerPosition))
    {
      Vector3 offsetToOriginal =
        localPointerPosition - 
        mOriginalLocalPointerPosition;
      UIDragElement.localPosition = 
        mOriginalPanelLocalPosition + 
        offsetToOriginal;
    }
  }Code language: JavaScript (javascript)

OnEndDrag

  public void OnEndDrag(PointerEventData eventData)
  {
    StartCoroutine(
      Coroutine_MoveUIElement(      
        UIDragElement,       
        mOriginalPosition,       
        0.5f));

    RaycastHit hit;
    Ray ray = Camera.main.ScreenPointToRay(
      Input.mousePosition);

    if (Physics.Raycast(ray, out hit, 1000.0f))
    {
      Vector3 worldPoint = hit.point;

      //Debug.Log(worldPoint);
      CreateObject(worldPoint);
    }
  }

Code language: C# (cs)
  • In the above code, the highlighted section uses a coroutine to reset the draggable UI’s position back to its initial position.
  public IEnumerator Coroutine_MoveUIElement(
    RectTransform r, 
    Vector2 targetPosition, 
    float duration = 0.1f)
  {
    float elapsedTime = 0;
    Vector2 startingPos = r.localPosition;
    while (elapsedTime < duration)
    {
      r.localPosition =
        Vector2.Lerp(
          startingPos,
          targetPosition, 
          (elapsedTime / duration));
      elapsedTime += Time.deltaTime;
      yield return new WaitForEndOfFrame();
    }
    r.localPosition = targetPosition;
  }
Code language: C# (cs)
  • Then, we do a raycast to determine where the ray intersects on the ground. If there is a hit, then we call the CreateObject method.
  • Finally, the CreateObject method is as below.
  public void CreateObject(Vector3 position)
  {
    if (PrefabToInstantiate == null)
    {
      Debug.Log("No prefab to instantiate");
      return;
    }
    GameObject obj = Instantiate(
      PrefabToInstantiate, 
      position, 
      Quaternion.identity);
  }
Code language: C# (cs)

Attach the Script and Configure

  • Go back to Unity editor and attach the DragUIItem script to each of the Inner images of Card1, Card2 and card3.
  • Select Inner from Card1 and associate the serialisable fields as below.
Associate the prefab, the draggable UI item and the canvas to the serialisable fields.
  • Similarly, do the same process for Inner from card2 and Inner from Card3 (with different prefabs).

Click Play and run the application. You should now drag the UI items onto the Ground and see the instantiated prefabs on the ground, as shown below.

Read My Other Tutorials

  1. Graph-Based Pathfinding Using C# in Unity
  2. 2D Grid-Based Pathfinding Using C# and Unity
  3. 8-Puzzle Problem Using A* in C# and Unity
  4. Create a Jigsaw Puzzle Game in Unity
  5. Implement a Generic Pathfinder in Unity using C#
  6. Create a Jigsaw Puzzle Game in Unity
  7. Generic Finite State Machine Using C#
  8. Implement Bezier Curve using C# in Unity
  9. Create a Jigsaw Tile from an Existing Image
  10. Create a Jigsaw Board from an Existing Image
  11. Solving 8 puzzle problem using A* star search
  12. A Configurable Third-Person Camera in Unity
  13. Player Controls With Finite State Machine Using C# in Unity
  14. Finite State Machine Using C# Delegates in Unity
  15. Enemy Behaviour With Finite State Machine Using C# Delegates in Unity
  16. Augmented Reality – Fire Effect using Vuforia and Unity
  17. Implementing a Finite State Machine Using C# in Unity
  18. Solving 8 puzzle problem using A* star search in C++
  19. What Are C# Delegates And How To Use Them
  20. How to Generate Mazes Using Depth-First Algorithm

Leave a Reply

Your email address will not be published. Required fields are marked *