Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 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 /
  • Help Room /
avatar image
14
Question by InDNA · Nov 07, 2015 at 09:22 PM · uiraycastcanvasscreenpointtoraymouseevent

Detect MouseOver/Click for UI Canvas Object

In my 2D game, there's an inventory system comprised of 20 inventory slots drawn on an UI canvas (displayed/hidden when the 'i' key is pressed).

I'm trying to add some menu functionality to the inventory, where you'd click an item slot and a small pop-up menu would be displayed with multiple, clickable options (equip, drop, info, etc.).


I tried adding a collider to my inventory slot prefab, so I'd be able to use a Raycast to detect when it's under the cursor:

 using UnityEngine;
 using System.Collections;
 
 public class MouseEvents : MonoBehaviour {
 
     public Camera mainCamera;
     
     // Update is called once per frame
     void Update () {
         RaycastHit2D hit;
 
         Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
         if(hit = Physics2D.Raycast(ray.origin, new Vector2(0,0)))
             Debug.Log (hit.collider.name);
     }
 }

This works just fine and fills the log when I mouse over a collider, but the inventory canvas is huge in relation to my scene. Like in the unity editor, this canvas is close to 30x larger than the level itself. The way it's displayed make's it look completely normal during runtime, but in the editor it's huge.


I guess what I need to know is:
How can my Raycast detect when the mouse is over an inventory slot, relative to what's being shown on screen at runtime.

Comment
Add comment
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

5 Replies

· Add your reply
  • Sort: 
avatar image
52
Best Answer

Answer by Statement · Nov 07, 2015 at 10:16 PM

How can my Raycast detect when the mouse is over an inventory slot, relative to what's being shown on screen at runtime.

My first reaction for seeing your script was wondering why you weren't using the EventSystem in Unity. Perhaps you don't know about it since it's kind of new or perhaps you have reasons not to. But I'll iterate what you should do to make your game work seamlessly (ish) with pointer events.

So you have a Canvas. I don't know if you thought about it, but the Canvas has what's called a Graphic Raycaster. This is what enables anything at all in the UI to even get a pointer event (mouse click/finger tap etc). The cool thing is that there are different kinds of Raycasters.

  • Graphic Raycaster is for UI inside a Canvas with a graphic.

  • Physics Raycaster is for 3D objects with a collider.

  • Physics 2D Raycaster is for 2D objects with a collider.

You could get rid of your own raycasts and use the Physics 2D Raycaster. To use it, add a Physics 2D Raycaster to your game camera. Unitys Event System (I don't know if you thought about it either, but when you create a canvas, it also creates an event system in the scene) works as such it lets input modules use raycasters to figure out what has been hit on the screen, then the "nearest" object is selected, and given events.

What you need to do on your 2D object is to have a script that handle input. You likely already have a script you can modify. To use these events is easy and there are three steps to it.

  1. using UnityEngine.EventSystems;

  2. Select the interface for the events you want to receive.

  3. Implement the interface methods with the code you want to run when your stuff is clicked.

An example:

 using UnityEngine;
 using UnityEngine.EventSystems; // 1
 
 public class Example : MonoBehaviour
     , IPointerClickHandler // 2
     , IDragHandler
     , IPointerEnterHandler
     , IPointerExitHandler
 // ... And many more available!
 {
     SpriteRenderer sprite;
     Color target = Color.red;
 
     void Awake()
     {
         sprite = GetComponent<SpriteRenderer>();
     }
 
     void Update()
     {
         if (sprite)
             sprite.color = Vector4.MoveTowards(sprite.color, target, Time.deltaTime * 10);
     }
 
     public void OnPointerClick(PointerEventData eventData) // 3
     {
         print("I was clicked");
         target = Color.blue;
     }
 
     public void OnDrag(PointerEventData eventData)
     {
         print("I'm being dragged!");
         target = Color.magenta;
     }
 
     public void OnPointerEnter(PointerEventData eventData)
     {
         target = Color.green;
     }
 
     public void OnPointerExit(PointerEventData eventData)
     {
         target = Color.red;
     }
 }

List of built in events.

Comment
Add comment · Show 2 · 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 Statement · Nov 07, 2015 at 10:27 PM 2
Share

Example doesn't work? A list of things to remember to have in case anything was unclear:

  • EventSystem in the scene to drive input events

  • Physics 2D Raycaster on the camera to drive hit detection

  • 2D Collider on the Object to enable hit detection

  • Script on the Object to handle input response

  • SpriteRenderer with a valid Sprite on the Object so we can see something happening

avatar image InDNA · Nov 11, 2015 at 10:18 PM 0
Share

Thank you!

avatar image
12

Answer by Krishx007 · Jul 31, 2019 at 01:37 PM

 ///Returns 'true' if we touched or hovering on Unity UI element.
 public static bool IsPointerOverUIElement()
 {
     return IsPointerOverUIElement(GetEventSystemRaycastResults());
 }

 ///Returns 'true' if we touched or hovering on Unity UI element.
 public static bool IsPointerOverUIElement(List<RaycastResult> eventSystemRaysastResults )
 {
     for(int index = 0;  index < eventSystemRaysastResults.Count; index ++)
     {
         RaycastResult curRaysastResult = eventSystemRaysastResults [index];

         if (curRaysastResult.gameObject.layer == LayerMask.NameToLayer("UI"))
             return true;
     }

     return false;
 }

 ///Gets all event systen raycast results of current mouse or touch position.
 static List<RaycastResult> GetEventSystemRaycastResults()
 {   
     PointerEventData eventData = new PointerEventData(EventSystem.current);
     eventData.position =  Input.mousePosition;

     List<RaycastResult> raysastResults = new List<RaycastResult>();
     EventSystem.current.RaycastAll( eventData, raysastResults );

     return raysastResults;
 }
Comment
Add comment · Show 4 · 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 Dayonel · Oct 06, 2019 at 07:05 PM 0
Share

Thank you very much, I think this is the best solution for a canvas.

avatar image sanchez_x · Jan 28, 2020 at 07:39 PM 0
Share

Thank you, works awesome!

avatar image JordanSchuetz · Apr 02, 2020 at 04:48 AM 0
Share

Thanks man this worked great for me. To get the elements in your update function just type: Debug.Log(IsPointerOverUIElement());

You can also add this for loop in GetEventSystemRaycastResults() function to output what UI element you are hovering on.

  foreach (var eventData2 in raysastResults)
 {
      Debug.Log(eventData2.ToString());
 }

avatar image Arxinos · Sep 01, 2020 at 11:11 AM 0
Share

Thank you very much, works as expected. Perfect!

avatar image
7

Answer by Nishat11 · Jan 05, 2018 at 06:31 AM

using UnityEngine.EventSystems;

check if(!EventSystem.current.IsPointerOverGameObject ()) than it will only detect mouse click on blank space not on canvas. you can also do the opposite with same.

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
2

Answer by Noctys · Sep 11, 2020 at 05:32 PM

I really like the answer from @Krishx007 -- I simplified it for my needs, figured I would share:

 public static bool IsPointerOverGameObject(GameObject gameObject)
 {
     PointerEventData eventData = new PointerEventData(EventSystem.current);
     eventData.position = Input.mousePosition;
     List<RaycastResult> raysastResults = new List<RaycastResult>();
     EventSystem.current.RaycastAll(eventData, raysastResults);
     return raysastResults.Any(x => x.gameObject == gameObject);
 }

Comment
Add comment · Show 1 · 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 ngduykhanh · Jul 16, 2021 at 02:34 PM 0
Share

Oh yeah, and this is my needs:

 public static bool IsPointerOverUI(string tag)
     {
         PointerEventData eventData = new PointerEventData(EventSystem.current);
         eventData.position = Input.mousePosition;
         List raysastResults = new List();
         EventSystem.current.RaycastAll(eventData, raysastResults);
         foreach (RaycastResult raysastResult in raysastResults)
         {
             if (raysastResult.gameObject.CompareTag(tag))
             {
                 return true;
             }
         }
         return false;
     }
 
 void Update()
     {
         if (Utils.IsPointerOverUI("UI")) {
             return;
         } //-- continue stuff
 
 }




avatar image
0

Answer by Cepheid · Nov 07, 2015 at 10:09 PM

Could you not just use Unity's built in UI Events within the UI system? With that you could simply create a public method and assign it to a mouseclick event component on a UI object which would then execute it when clicked.

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

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

43 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 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

OnPointerEnter blocked by something 2 Answers

Laser pointer style UI interaction in VR 2 Answers

Unity Button reacts even if Canvas is disabled 0 Answers

Block Raycast with Ui in Andoid 0 Answers

How to physics raycast through overlay UI? 1 Answer


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