Check if mouse is over a Rect problem...

Hi, i’ve been looking for several hours for this problem.

I have several Slots in an inventory, and i’m creating my own drag/drop system. So I check if the mouse is over a slot for each slot like this :

        for(int i = 0; i<compteurSlots; i++)
        {
         
            if (this.transform.parent.GetChild(0).GetChild(i).GetComponent<RectTransform>().rect.Contains(Input.mousePosition))
            {
                Debug.Log("mouse above: " + this.transform.parent.GetChild(0).GetChild(i).name);
            }
            else
            {
                Debug.Log("nothing under the mouse");
            }

        }

But nothing appears in the console, do you have any ideas ?

thanks !

Is it erroring out? Is that function being called? Is “compteurSlots” 0?

CompteurSlots is 30 (because there are 30 slots), no erros, the if statement is never trigered… even if my mouse is in the rect…

If you see no debug statements in the console, then your for loop is not being reached. Try to debug before the for loop. Print out some values, find out where the code is getting to.

actually, I explained badly my problem… (sorry for my english ^^)… The probleme is that the console shows “nothing under the mouse” even if I have a slot under…

“this.transform.parent.GetChild(0).GetChild(i).GetComponent().rect.Contains(Input.mousePosition)”

This is hard to understand and likely to break with null references.

Note that “Input.mousePosition” is in ScreenSpace, but “RectTransform.rect” is a local relative positions.

You would need to convert the rect to world space by doing something like this:

However, you’re doing things the hard way. There are other built-in ways in Unity to detect mouse events.

See these links:

https://docs.unity3d.com/ScriptReference/UI.Selectable.OnPointerEnter.html
https://docs.unity3d.com/ScriptReference/UI.Selectable.OnPointerExit.html

Ok i had a look at OnPointerEnter(), but when I drag an item, it follows the mouse position. So if i use onPointerEnter, it will only detect the item instead of the slots under.

I tried to disable the collider, but I can’t drag any item without it…

Is there a way to ignore my item in my onPointerEnter() function ?

    public void OnDrag(PointerEventData eventData)
    {
        drag = true;
       
        this.transform.position = Input.mousePosition;
         LastSlot = eventData.pointerEnter;
       Debug.Log(eventData.pointerCurrentRaycast.gameObject);
    }

Add a canvas group to your item (doesn’t need a collider , btw) and when you’re dragging, set the canvas group “blocks raycast” to false. Come to think of that, you can probably do that on the image, also. Anyways, that’s how I learned (canvas group) :slight_smile:
Restore the blocks raycast after you drop it.

1 Like

methos5k I tried your solution but the problem is the same. with a canvasGroup + block Raycast = false, i can’t drag my item.
Maybe i did something wrong with my Dragging code :

 void IBeginDragHandler.OnBeginDrag(PointerEventData eventData)
    {
        startPoint = this.transform.position;
        parentStart = this.transform.parent;
        this.transform.SetParent(this.transform.parent.parent.parent);
      
    }

    public void OnDrag(PointerEventData eventData)
    {
        drag = true;
        this.transform.position = Input.mousePosition;
        LastSlot = eventData.pointerEnter;
       Debug.Log(eventData.pointerCurrentRaycast.gameObject);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        drag = false;
         if(LastSlot != null && LastSlot.name.Contains("Slot")) {
                Debug.Log("I will put my item on slot: " + LastSlot);
            }
            else
            {
                Debug.Log("No slots found");
            }

        this.transform.position = startPoint;
        this.transform.SetParent(parentStart);
    }

Thank you !

Yes, you have to disable it when you begin dragging & re-enable it at the end :slight_smile:
Otherwise, you can’t drag as you noticed.
When it’s disabled, your pointer events will “pass through” though, which is what you want… :slight_smile:

There’s also an OnDrop event if you didn’t know.

1 Like

Thanks for your answer, i will try your solution ! What is the difference between OnEndDrag and onDrop events?

Well, OnEndDrag happens when you’re done dragging (and is called on the object you’re dragging*)… Like I see you are attempting to mimic drop in some way by updating the pointerEnter it looked like.
OnDrop happens when you’re dragging an object, and then (let’s call it a slot - underneath - has an OnDrop interface), that place underneath will receive that event…

1 Like

Oh god, thanks ^^

heh, no problem :slight_smile:

Ok I did it with onDrop, but now i have two separate scripts…One on the grid Layout that contain all the slot and which manage the inventory (for instance an object with positon = 3 will be on the third slot)… To do that i create a class named “slot” which contain an item, a int (for amount) and a position… but how to change these variables since they are in another file…

Or actually, how to get the previous position of the dragged item ? Is that PressPosition ?

Just 1 script manages all of the slots? Or one on each slot?
if it’s one you can reference it just in a variable on each drop script.
if it’s on each slot, that you drag… you can look it up when the drop happens.
I think it’s eventData.pointerDrag.GetComponent()
:slight_smile:

Perfect !

One last question more abstract…, i’m trying to avoid any item from being lost.

So I did this :

        if (LastSlot == null || !LastSlot.name.Contains("Slot") || !LastSlot.transform.parent.name.Contains("Slot")) {
            this.transform.position = startPoint;
            this.transform.SetParent(parentDepart);
        }

My aim is to determine if the item is above a slot or not…
But this doesn’t work…
I think I have a problem with || because during my studies I learned that there was a inclusive way and another…

Ok I found, the answer was:

   if (LastSlot == null || (!LastSlot.name.Contains("Slot") && !LastSlot.transform.parent.name.Contains("Slot"))) {

Thanks again for your time !

Okay, that solution sounds good. Glad it’s working for you. :slight_smile: