Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by KurtGokhan · Jan 23, 2015 at 10:40 PM · uieventsystempointerevent-handling

Catch pointer events by multiple gameObjects

I noticed if there is a panel in front of another, mouse events will not reach panels in the back. Is there a way around? I guess it is not working because RayCast is blocked. But can't RayCasts get multiple hits? Why was it designed like this?

Example Case: The panel on front uses OnPointerClick event and panel on the back uses OnPointerEnter. When you come over panels I want OnPointerEvent on the back panel to be called and when I click I want OnPointerClick to be called.

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image lodendsg · Dec 15, 2016 at 05:57 PM 0
Share

I have a similar situation in that I need to respond to an event in 1 control but not block the message from events behind it.

In my case I am using the mouse enter and exit to control when a camera is aloud to scroll, this works wonderfully in that mouse over a UI element and it wont scroll happy days, but unfortunately it also means everything behind that (selectable objects in the world) now wont respond to my events.

The ideal solution is that I can respond to mouse enter and exit, can block events with other elements such as input fields but that I dont block events with a particular element (my zoom RECT)

I can code this manually I suppose testing for cursor location in a given RECT space, testing to see if if another element control has focus, etc. but what a pain, would be so much easier if we could toggle in some way rather or not a received message was intercepted or passed on ... anyone have a simpler solution using stock Unity elements that I missed?

And no a custom handler which only listens to enter exit wont work as I need enter and exit to continue on to the game space not just the click which is what I have at the moment.

6 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by InvincibleCat · Jan 23, 2015 at 10:42 PM

Use the layers.

You can set the blocking mask directly on your canvas.

UPDATE:

FOUND THE SOLUTION

You need to have your 2 Canvas set to Screen Space Camera and affect the same Camera to the canvas

Comment
Add comment · Show 21 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KurtGokhan · Jan 23, 2015 at 10:45 PM 1
Share

What if I want both panels on same canvas?

avatar image InvincibleCat · Jan 23, 2015 at 10:48 PM 0
Share

What for?

avatar image KurtGokhan · Jan 23, 2015 at 10:49 PM 0
Share

Okay, seems like I misunderstood the whole canvas thing. What you say works. Do you know if this will work if I want to catch same event in different panels at the same time?

avatar image InvincibleCat · Jan 23, 2015 at 10:53 PM 0
Share

Yes. If it is in 2 separate layers

avatar image KurtGokhan · Jan 23, 2015 at 11:01 PM 1
Share

Actually, It doesn't work. I don't think you understand what I mean or I don't understand you. When I add CanvasGroup on the panel in the front and set "BlocksRaycast" to false, I can catch events in the back but not in the front. If I don't add CanvasGroup, I can catch events in the front but not back. I am actually looking for a way to catch events in both panels. I can't put them in seperate canvas because panel in the front is child object of panel in the back.

Show more comments
avatar image
1

Answer by immersiveGamer · Jan 26, 2015 at 10:13 PM

What you are looking for is Physics.RaycastAll. This returns all hits along the ray instead of the first one. Of course this means it returns an array of RaycastHits which you will need to loop through.

Here is an example of use. Hopefully this helps in allowing for you to have overlapping objects and multiple events:

 void SendEvents()
 {
      Ray ray = rayFromMouse; //the ray you are making
      RaycastHit[] hits; //the array of hits. 
 
      hits = Physics.RaycastAll(rayFromMouse);
 
      if(hits.Length > 0)
      {
           for(int i = 0; i < hits.Length; i++)
           {
                hits[i].transform.GetComponent<MyEventScript>().CallEvent();
           }
      }
 }


Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KurtGokhan · Jan 27, 2015 at 08:00 AM 0
Share

Hi. Thanks for reply but I am looking for a way to call pointer events on 4.6 UI elements. Like OnPointerExit, OnBeginDrag etc. I think they would be more efficient and robust if there was an easy way (Which I think there is certainly one but I don't know yet) Also implementing every evet this way would take much time.

avatar image immersiveGamer · Feb 06, 2015 at 09:57 PM 0
Share

hmmm, so I looked into it and it seems that when an object gets interacted with it intercepts the event.

alt text

I don't know how you can over come this. I tried assorts of things but to no avail couldn't get it to work. Things like changing the graphic raycaster on the canvases, multiple canvases, dug into the documents and tried to get something. What is a real pain is that a Event Trigger actually intercepts everything! Wouldn't it be the other way round? I tried looking for a way to change the Intercepts (which I assume is some kind of delegate it gets added to) but couldn't do that either. Perhaps there is a graphical/spacial way to solve your problem? Like making sure the panel behind sticks out a bit? Or use transparency? I know I read somewhere that we have access to the source code for the new UI and thus can make changes as we need.

Also it really wouldn't take too much time to make your own event system. Unity already tracks clicks, drags, etc. and you just make delegates. I did something similar with the old OnGUI system and it worked just fine. $$anonymous$$aybe I'll look into the source code (they are just C# scripts by the way) and see if I can hack anything together.

avatar image KurtGokhan · Feb 07, 2015 at 12:48 AM 0
Share

You can always design your own raycaster, collider, input manager etc. There is always a way around any problem. But what is the purpose of the game engine then? If there was a way to do it naturally, it would also be faster.

I just think this behavior is not intended or planned to be improved in newer versions. It makes no sense that it lacks this functionality, because it seems to me like it is something anyone could have needed.

avatar image
1

Answer by jonaslindberg · May 07, 2020 at 06:23 AM

This is how I solved passing on any PointerEvent type to the next Raycast-blocking item underneath. It's easy to implement some check for a specific Tag, Component etc. if you have many blocking objects stacked...

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UI;
 using UnityEngine.EventSystems;
 
 public class PassOnPointerEvent : MonoBehaviour, IPointerDownHandler, IDragHandler, IBeginDragHandler, IPointerUpHandler, IEndDragHandler
 {
     GameObject newTarget;
 
     public void OnPointerDown(PointerEventData eventData)
     {
         List<RaycastResult> raycastResults = new List<RaycastResult>();
         EventSystem.current.RaycastAll(eventData, raycastResults);
         newTarget = raycastResults[1].gameObject; //Array item 1 should be the one next underneath, handy to implement for-loop with check here if necessary.
         print($"Passing on click to {newTarget}"); //Just make sure you caught the right object
 
         ExecuteEvents.Execute(newTarget, eventData, ExecuteEvents.pointerDownHandler);
     }
 
     public void OnPointerUp(PointerEventData eventData)
     {
         ExecuteEvents.Execute(newTarget, eventData, ExecuteEvents.pointerUpHandler);
     }
 
     public void OnBeginDrag(PointerEventData eventData)
     {
         ExecuteEvents.Execute(newTarget, eventData, ExecuteEvents.beginDragHandler);
     }
 
     public void OnDrag(PointerEventData eventData)
     {
         ExecuteEvents.Execute(newTarget, eventData, ExecuteEvents.dragHandler);
     }
 
     public void OnEndDrag(PointerEventData eventData)
     {
         ExecuteEvents.Execute(newTarget, eventData, ExecuteEvents.endDragHandler);
     }  
 }

Hope it can help someone!

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image felixmann · May 15, 2020 at 04:13 PM 0
Share

Hm, it seems to call ExecuteEvents.Execute on the correct game object, but that game object's OnPointerDown() is not called :/ Any idea what I could be doing wrong?

avatar image jonaslindberg felixmann · May 17, 2020 at 07:12 PM 1
Share

Hmm, hard to say from here of course but first check that your action is relying on the PointerDown event and not e.g. PointerClick?

Otherwise, try "bubbling" the event at the found target GameObject and then getting the actual GameObject that will be reliable for executing by using the GetEventHandler function. Something like below...

 public void OnPointerDown(PointerEventData eventData)
 {
     List<RaycastResult> raycastResults = new List<RaycastResult>();
     EventSystem.current.RaycastAll(eventData, raycastResults);
     newTarget = ExecuteEvents.GetEventHandler<IPointerDownHandler>(raycastResults[1].gameObject)
     
     ExecuteEvents.Execute(newTarget, eventData, ExecuteEvents.pointerDownHandler);
 }



This also means you can do something like below to do completely fake pointer events.

 public Vector2 fakePointerPos;
 
 [Context$$anonymous$$enu("Fake Click!")]
 public void FakePointerDownEvent(fakePointerPos)
 {
     PointerEvenData constructedEventData = new PointerEvenData(EventSystem.current);
     constructedEventData.position = fakePointerPos;
 
     List<RaycastResult> raycastResults = new List<RaycastResult>();
     EventSystem.current.RaycastAll(constructedEventData, raycastResults);
     newTarget = ExecuteEvents.GetEventHandler<IPointerDownHandler>(raycastResults[0].gameObject) //assu$$anonymous$$g you want to collect the first object at this position
     
     ExecuteEvents.Execute(newTarget, constructedEventData, ExecuteEvents.pointerDownHandler);
 }

The Context$$anonymous$$enu stuff is just so you can run it from the dropdown menu in Editor, the three dots to the right of the script title.

avatar image Melnikovv felixmann · Mar 18 at 08:04 PM 0
Share

Leave only "IPointerDownHandler, IPointerUpHandler" And then this script will work fine

avatar image
0

Answer by Radetic · Apr 22, 2015 at 09:02 PM

It seems like you're trying to do some sort of event bubbling in a sense.

What you can do, since the front panel is a child of the back panel, is calling the same method in back panel that is called OnPointerEnter by it's EventTrigger in the front panel's EventTrigger as well.

In other words, you would make the child intercept the event and send it to it's parent inside your own callback (whatever public void method you give to the EventTrigger for this).

Hope it works!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Stridemann · Apr 20, 2017 at 09:19 AM

If someone will read this.. I found solution for me.

In my case the event is fired for first layer, then to parent layers, but I need only the first event (for top object), so its easy to filter events by frame number:

 private int frameNum;
 public void OnPointerEnter(PointerEventData eventData)//OnPointerEnter, but you can use any other events
 {
       if (frameNum == Time.frameCount) return;
     frameNum = Time.frameCount;

     //Do your stuff here
 }

Only the first event will pass (for toppest object).

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

IPointer Events don't seem to be working 3 Answers

IPointerEnterHandler doesn't work when object switches parent 1 Answer

PointerEnter / PointerExit keeps triggering on UI Element 0 Answers

Fake pointer up on UI gameobject A and pointer down on UI gameobject B 1 Answer

How do i get the child of an GameObject the pointer is hovering over? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges