How to use OnPointerUp without the pointer going down on the same object?

I’m trying to create a drag & drop interface where the user drags a ghosted element from one area of the UI and drops it on another. The drop area implements IPointerEnter, IPointerExit, and IPointerUp.

I successfully change the color of the area with OnPointerEnter and OnPointerExit for when the user drags the appropriate type of object into the area. However, when the use drops the object in the area, OnPointerUp is not getting called.

I have run some tests and it seems like for OnPointerUp to be called, the mouse has to go down on the same object first.

Is there a way to solve this problem? It seems to me that the difference between OnPointerUp and OnPointerClick should be what I’ve described - a click is when down/up happens on the same object, but I would think up would just get called any time the mouse goes up over an object.

Or am I looking at this wrong: do I need to do this in a script on the thing being dragged, and use OnEndDrag? I would prefer not to do this, because I want the place the object is dropped in to drive what happens.

So, I feel a little silly, but there is actually an IDropHandler with an OnDrop(PointerEvent i_event) method. So, this is the thing to use when you want to know if something has been dropped on an element, not IPointerUpHandler… :slight_smile:

“for OnPointerUp to be called, the mouse has to go down on the same object first” Sounds right. Even if this weren’t the case, I’m pretty sure all UI elements consume events, so your OnPointerUp call would get swallowed by the element you are dragging.

In several cases akin to yours (doing something a little unconventional with the UI) I’ve had to write some messy workarounds. However distasteful I found these solutions, they never seemed to break once I worked out the quirks. I do not know of an alternative answer in keeping with UI guidelines and UI’s conveniences. There’s no law against enforcing your own logic upon the UI and Event systems. :slight_smile:

REVISION
In case it’s helpful to others in the future, I’m sharing the pattern I use to interface with Unity’s UI elements / events. You can spoof a PointerEventData object and use it to raycast into UI space and return a list of hits. This allows you to sidestep every limitation of Unity’s native event paradigm and invoke your own custom logic.

You can implement custom element-dragging logic. Also stuff like making a button respond (and respond differently) to right-clicks. Or having logic capable of “seeing” every element beneath the cursor, rather than the topmost only.

var pointer = new PointerEventData(EventSystem.current);
pointer.position = Camera.main.WorldToScreenPoint( GSM.MouseOnUI );		
var raycastResults = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointer, raycastResults);
			
foreach (RaycastResult result in raycastResults) {
	// Apply Custom Logic Here
    MyComponent foo = result.GetComponent<MyComponent>();
    if (foo != null) {
    	if (Input.GetMouseButton(0)) {
	    	Debug.Log("left-clicked on " + foo.name);
	    }
    }
}