Drag & Drop system: IDropHandler event not called?

Hi, I’ve took a look at the Drag & Drop example file and tried to implement the same for my inventory UI. But when I try combining some of the methods in DragMe.cs and DropMe.cs, the OnDrop() method of IDropHandler event is never called. What seems to be the issue?

I combined the scripts because Ithe items are dragged from one inventory slot to another similar slot, so it needs to be both draggable and droppable, if that makes sense. Cheers

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

public class InventoryItemTracker : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler
{
    public int slot = 0;

    public int GetSlot()
    {
        return this.slot;
    }

    public void SetSlot(int index)
    {
        this.slot = index;
    }


    // DRAG
    public void OnBeginDrag(PointerEventData eventData)
    {
        Debug.Log ("BEGIN DRAG");

        GUIManager.instance.InventoryDragItem(this.slot);

        GUIManager.instance.SetItemDragPlane(transform as RectTransform);

        // Update dragging Item position
        GUIManager.instance.InventoryIsDraggingItem(eventData);
    }

    public void OnDrag(PointerEventData data)
    {
        Debug.Log ("ON DRAG");

        // Update dragging Item position
        GUIManager.instance.InventoryIsDraggingItem(data);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        Debug.Log ("END DRAG");
    }

    // DROP
    public void OnDrop(PointerEventData data)
    {
        Debug.Log ("ON DROP");
    }
}

Do you have a graphic on the target? The raycaster we use is based on graphics.

2 Likes

Thanks Tim. Apparently it was a silly mistake of mine.
I forgot to add the IgnoreRaycast.cs script onto the dragging object when I replaced it with a prefab!

Cheers

1 Like

This is good info - Thank you to both of you. Didn’t catch the IgnoreRayCast part until I read this thread.

Managed to boil down both drag and drop to rudimentary versions that are less than 10 lines both. I borrowed the IgnoreRayCast.cs part from example.

I really don’t understand exactly what part of Event System uses it? To what it passes it’s data?

This is how I used it:
Add it in OnPointerDown, when start dragging an object (to dragged object).
Remove it in OnEndDrag, when stop dragging.

I suspect this: Raycast information “goes” to EventSystem itself, as manual states it “Manages Raycasting” and in this case Canvas object has Graphic Raycaster script… so when object I drag has IgnoreRayCast.cs component it puts out false and is ignored by GraphicRaycaster, and it’s possible for EventSystem to see object under it? Manual is very short on information about this.

Please clarify if possible - Thank you :slight_smile:

Hope there will be more simple examples later (after beta) !

eses, the problem you’re having seems to be a bit of confusion around what “drag” is.
OnPointerDown registers the touch or mouse down input, not the start of a drag. It’s useful for hold to click or something similar, but it doesn’t tell the event system “hey, I started dragging, listen for a drop”

The IDragHandler OnDrag(PointerEventData) will tell the event system “Hey, I’m dragging, listen for a drop”…
Or maybe the IBeginDragHandler OnBeginDrag(PointerEventData)…

I’ve been bashing my face against the event system all week, but I think that may solve your issue. It’s not that the raycast doesn’t see the OnDrop object, it just doesn’t care because you didn’t tell it you were dragging.

Or maybe I just misunderstood what you were saying.

Cheers

Edit: Oops, necro’d a thread because it was one of the few I found in my searches. Hopefully it helps whoever stumbles here.

1 Like

Hi all ! My problem is kind of same but it is apparently working fine when i drag one instance and drop in on any other instance (Then OnDrop() is working). However if i drag an instance from any object and drop it on same dragged instance (Object from where i dragged it) then its OnDrop() method is not working, meanwhile its onPointerEnter() OnPointerExit() are working. I have two scripts on every object i-e DragMe and DropMe. Please help me out and save my life. Thanks in advance.

A late addition to this thread for those still searching for an answer :smile:. I had the same problem in a 2D card game I’ve been working on, and after many hours have just worked it out. It was all to do with the thickness (collider Z scale) of the objects I was dragging/dropping and their Z transform position value. When dropping on an object I would re-parent that object to the container and set the transform position to that of the parent (using my own custom layout class) - at that point I was never able to drop it on another container. All I had to do when dragging was to bring the object closer to the camera (e.g. transform.position.z = -0.1f) and then all would work fine again. I also had to make sure all my containers were z = 0.01f to put them just back a little. Such a simple logic error but it’s taken me hours to figure it out.

I hope this helps some fellow traveler in future. :roll_eyes:

I spent hours figuring out why my onDrop wasn’t called, it was because the IPointerDownHandler eats my drop event

3 Likes

Thanks Pinda !!

This is my trick when dragging item blocks drop target:

  1. Disable dragging raycast target in OnBeginDrag.
  2. Enable dragging raycast target in OnEndDrag.
  3. OnDrag() will work anyway.
  4. Drop target object will get OnDrop event. Even it’s behind in the hierarchy.

Here is an example:

public class DragItem : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
    {
        [SerializeField] protected Graphic _raycastTarget;
        [SerializeField] protected RectTransform _itemTrans;
       
        public void OnDrag(PointerEventData eventData)
        {
            RectTransform parent = _itemTrans.parent as RectTransform;
            bool success =
                RectTransformUtility.ScreenPointToLocalPointInRectangle(
                    parent,
                    eventData.position,
                    eventData.enterEventCamera,
                    out Vector2 locPos);

            if (success)
            {
                _itemTrans.anchoredPosition = locPos;
            }
        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            _raycastTarget.raycastTarget = false;
        }

        public void OnEndDrag(PointerEventData eventData)
        {
            _raycastTarget.raycastTarget = true;
        }
    }
1 Like