- Home /
4.6 New UI: MouseOver event/function needed
I'm quite new, and fear I'm a bit lost.
I need an OnMouseOver function/event in order to determine when a script/function can be run on a certain UI element such as a panel. I've tried PointerEnter/Exit events, and while they do work to a certain extent, I really need something that runs every frame In order to detect if certain conditions are met.
I've attempted to use a script with an OnMouseOver function attached to a UI panel, but it doesn't seem to work. The same script works fine with a basic cube object. I placed a 2D box collider on the panel, resized it to fit, but the script still did not work.
I could probably manage with an PointerOver event, but I can't seem to find one.
Thank you in advance!
Ps. I'm attempting to get multiple UI "windows" with the same or similar scripts to work well with each other. They all check where the cursor currently is, and act upon its positioning. The problem comes when their positions overlap. Again, the PointerEnter/Exit events allow me to control which object/script runs to an extent, but without the events running until conditions change, they don't allow me full control.
Answer by DCTShinobi · Feb 19, 2015 at 08:47 PM
For anyone still interested, I actually ended up creating my own "Mouse Over" style function that works for UI objects using the default canvas settings. The following is a streamlined version.
First, to detect when the cursor is over the scripted UI object...
void Update ()
{
RectTransform objectRectTransform = gameObject.GetComponent<RectTransform> (); // This section gets the RectTransform information from this object. Height and width are stored in variables. The borders of the object are also defined
float width = objectRectTransform.rect.width;
float height = objectRectTransform.rect.height;
float rightOuterBorder = (width * .5f);
float leftOuterBorder = (width * -.5f);
float topOuterBorder = (height * .5f);
float bottomOuterBorder = (height * -.5f);
// The following line determines if the cursor is on the object
if(Input.mousePosition.x <= (transform.position.x + rightOuterBorder) && Input.mousePosition.x >= (transform.position.x + leftOuterBorder) && Input.mousePosition.y <= (transform.position.y + topOuterBorder) && Input.mousePosition.y >= (transform.position.y + bottomOuterBorder))
{
PerformRaycast (); // Calls the function to perform a raycast
}
}
Then, use a graphic raycast to determine if the scripted object is actually the fore-most UI object where the cursor is positioned...
void PerformRaycast () // This function performs a raycast to detect if this object is in front of other objects if any overlap at the cursor's position when the mouse button is initially pressed
{
PointerEventData cursor = new PointerEventData(EventSystem.current); // This section prepares a list for all objects hit with the raycast
cursor.position = Input.mousePosition;
List<RaycastResult> objectsHit = new List<RaycastResult> ();
EventSystem.current.RaycastAll(cursor, objectsHit);
int count = objectsHit.Count;
int x = 0;
if(objectsHit[x].gameObject == this.gameObject)
{
// This section runs only if this object is the front object where the cursor is
}
}
Using more comprehensive versions of the above code, I've created an entire package of scripts that is available on the asset store. All scripts are fully commented, and there are many example scenes included.
**Move & Resize UI on the Asset Store**
Version 3.0 Webplayer Demo and Full Readme
I do hope this helps! Good luck!
Answer by fafase · Nov 26, 2014 at 07:52 PM
If you have the PointerEnter and the PointerExit then just use an update or a coroutine:
bool isInside = false;
void OnPointerEnter(ped)
{
isInside = true;
}
void OnPointerExit(ped)
{
isInside = false;
}
void Udpate(){
if(isInside){}
}
with a coroutine:
bool isInside = false;
void OnPointerEnter(ped)
{
if(isInside == false)
{
StartCoroutine("UpdateCoroutine");
}
}
void OnPointerExit(ped)
{
StopCoroutine("UpdateCoroutine");
isInside = false;
}
IEnumerator UpdateCoroutine(){
isInside = true;
// do your stuff
yield return null;
}
Note that there might be an event from UnityEngine.EventSystem that handles this but I can recall...neither can I recall the exact type of the paramaters...PointerDataEvent I think it is
Thank you very much for that info. It is very helpful, and definitely gives me a direction to work from.
If you don't $$anonymous$$d me asking, though, because I am still trying to wrap my $$anonymous$$d around things, would it be effective in the following example?
I have two draggable panels. I have PointerEnter and Exit events on them both that follow your code above. I drag one panel to overlap the other, but the cursor actually gets ahead of the panel getting dragged, and enters the other panel. Would there be a way to ignore setting "isInside" to true on the stationary panel UNTIL the mouse button is released AND confir$$anonymous$$g that the cursor is not on top of the panel that was dragged (assu$$anonymous$$g that it may have caught up to the cursor)?
That is, I want the "isInside" to be set to true after I release the mouse button, but not before. I've set a condition up like that with my current code, though if the PointerEnter event takes place with the mouse button down, it never updates when the mouse button is released. That's why I thought a $$anonymous$$ouse/PointerOver event/function may do the trick. I even tried to combine the PointerEnter/Exit events with PointerUp/Down/Click events to achieve the effect, though they don't seem to succeed either.
But definitely thank you again. I'll try to implement what you shared and see how it goes!
Answer by TimK_gumi · Nov 26, 2014 at 10:14 PM
Add a collision rect to your UI element
Create a component
In the component's Update function, do a Physics2D raycast and detect whether you get a collision with your UI element (possibly by checking against its name).
Thank you for the suggestion. I found out that the $$anonymous$$ouseOver function was not working because my canvas is set to Screen Space - Overlay, so I'm assu$$anonymous$$g that the cursor never actually scrolls "over" my UI panel. Changing the canvas to use Screen Space - Camera fixes the problem, but brings up a whole new set of issues.
I may very well try the raycast method. Thanks again!
Answer by knokko · Dec 17, 2015 at 03:14 PM
Another way to accomplish this is to use Animation Events. Set as Transition for the button an animation. Then in the "Highlighted Trigger" animation, add an animation event which calls your desired method. No programming required.
Interesting. Thank you. I'll keep that in $$anonymous$$d in case I need to change something in my script pack. Have a very $$anonymous$$erry Christmas!
Your answer

Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Chain UI animations with Events? 1 Answer
UI image with button component not tracking mouse correctly 1 Answer
UI canvas, toggle question 0 Answers