Search Unity

OnPointerExit not always firing?

Discussion in 'UGUI & TextMesh Pro' started by Avalin, Apr 3, 2019.

  1. Avalin

    Avalin

    Joined:
    Oct 12, 2018
    Posts:
    98
    I'm trying to make a tooltip. Currently I have a few buttons next to one another which should get highlighted in the OnPointerEnter function, and of course, stop highlighting in the OnPointerExit function.

    For the most on this works fine, however, these buttons are rather close to one another, let's call them "Attack" and "Defend", if I move my mouse slowly from "Attack" to "Defend" my tooltip changes accordingly. However when I quickly move my mouse from "Attack" to "Defend" it will keep showing "Attack" as if the update for onPointerExit was never called in the small gap there is between them, if the mouse moves fast enough.


    I have a similar setup with GameObjects using OnMouseOver that works completely fine, but with these UI elements I can't make it work properly.

    Here's my code:


    Code (CSharp):
    1. public class TooltipManager : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
    2. {
    3.     GameObject currentHover;
    4.  
    5.     void Update()
    6.     {
    7.         if (currentHover)
    8.         {
    9.             Debug.Log(currentHover.name + " @ " + Input.mousePosition);        
    10.         }
    11.     }
    12.  
    13.     public void OnPointerEnter(PointerEventData eventData)
    14.     {
    15.         if (eventData.pointerCurrentRaycast.gameObject != null)
    16.         {
    17.             Debug.Log("Mouse Over: " + eventData.pointerCurrentRaycast.gameObject.name);
    18.             currentHover = eventData.pointerCurrentRaycast.gameObject;
    19.             Tooltip.ShowTooltip(currentHover.name);
    20.         }
    21.     }
    22.  
    23.  
    24.  
    25.     public void OnPointerExit(PointerEventData eventData)
    26.     {
    27.         Debug.Log("Exit hover");
    28.         currentHover = null;
    29.         Tooltip.HideTooltip();
    30.     }
    31. }
     
  2. Paradoks

    Paradoks

    Joined:
    Oct 13, 2009
    Posts:
    436
    Hello,
    Did you find a workaround ? I got the same problem.
     
    sean244 and Avalin like this.
  3. Avalin

    Avalin

    Joined:
    Oct 12, 2018
    Posts:
    98
    Unfortunately not, this is still on my bug list to-be-fixed :(
    I'll definitely update this thread if I ever find a workaround.
    I suppose using gameobjects instead would work, but it's such a dirty solution I'd rather not do so
     
  4. zheyuanzhou

    zheyuanzhou

    Joined:
    Oct 29, 2017
    Posts:
    22
    I faced the Same problem now
     
    sean244 likes this.
  5. zheyuanzhou

    zheyuanzhou

    Joined:
    Oct 29, 2017
    Posts:
    22
    I fixed my problem. I problem is that I used OnPointerExit/OnPointerEnter to show/Display the Tooltip on my game. When I Hover this Item, The ToolTips always blink(one Display one Hide many times in one second). I used one hour to search for the answer. FInally, I found one solution I did not need to change the Interface even code. I only need to change the pivot point of my Tooltips in my game(One UI IMAGE GameObject). Here is my code.

    [This is my solution so that might be not targeted for your situation, But I really face the same situation And search and found your Post]

    Call this Function inside Update
    Code (CSharp):
    1. private void UpdateTooltip()
    2.     {
    3.         Vector2 pos;
    4.         //RectTransformUtility.ScreenPointToLocalPointInRectangle(GameObject.Find("Menu Canvas").transform.GetChild(0).transform.GetChild(2).transform as RectTransform, Input.mousePosition, null, out pos);
    5.         RectTransformUtility.ScreenPointToLocalPointInRectangle(GameObject.Find("Menu Canvas").transform as RectTransform, Input.mousePosition, null, out pos);
    6.  
    7.         if (isShow)
    8.         {
    9.             tooltip.ShowTooltip();
    10.             tooltip.SetLocationPosition(pos);
    11.         }
    12.         else
    13.         {
    14.             tooltip.HideTooltip();
    15.             tooltip.SetLocationPosition(pos);
    16.         }
    17.     }
    18.  
    19. #region Observer Pattern
    20.     private void OnEnter()
    21.     {
    22.         //Debug.Log("OB ENTER");
    23.         isShow = true;
    24.     }
    25.  
    26.     private void OnExit()
    27.     {
    28.         //Debug.Log("OB EXIT");
    29.         isShow = false;
    30.     }
    31.  
    Screen Shot 2019-10-05 at 3.01.18 AM.png

    Screen Shot 2019-10-05 at 3.01.40 AM.png
     
    Avalin likes this.
  6. zheyuanzhou

    zheyuanzhou

    Joined:
    Oct 29, 2017
    Posts:
    22
    And This is my ItemButton Code

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.EventSystems;
    6. using System;
    7.  
    8. public class ItemButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
    9. {
    10.     public int buttonID;
    11.     public Image itemButtonImage;
    12.     [HideInInspector] public Text itemNumberText;
    13.  
    14.     #region Observer Pattern
    15.     public static Action onEnter;
    16.     public static Action onExit;
    17.     public static Action OnLeftBeginDrag;
    18.     public static Action OnLeftDrag;
    19.     public static Action OnLeftEndDrag;
    20.     #endregion
    21.  
    22.  
    23.     private void Start()
    24.     {
    25.         itemNumberText = GetComponentInChildren<Text>();
    26.     }
    27.  
    28.     //TODO Mouse Hover Later & Add TARGET Image hit OR BG Color change
    29.     //MARKER When you press the ItemBUTTON, You will CALL thie FUNCTION
    30.     public void PressItemButton()
    31.     {
    32.         if(GameManager.instance.itemsHeld[buttonID] != "")
    33.         {
    34.             GameMenu.instance.SelectItem(GameManager.instance.GetItemDetail(GameManager.instance.itemsHeld[buttonID]));
    35.         }
    36.     }
    37.  
    38.  
    39.     #region event
    40.     public void OnPointerEnter(PointerEventData eventData)
    41.     {
    42.         if (onEnter != null)
    43.         {
    44.             onEnter();
    45.         }
    46.     }
    47.  
    48.     public void OnPointerExit(PointerEventData eventData)
    49.     {
    50.         if (onExit != null)
    51.         {
    52.             onExit();
    53.         }
    54.     }
    55.     #endregion
    56.  
    57.     public void OnDrag(PointerEventData eventData)
    58.     {
    59.         if (OnLeftBeginDrag != null)
    60.         {
    61.             OnLeftBeginDrag();
    62.         }
    63.     }
    64.  
    65.     public void OnBeginDrag(PointerEventData eventData)
    66.     {
    67.         if (OnLeftDrag != null)
    68.         {
    69.             OnLeftDrag();
    70.         }
    71.     }
    72.  
    73.     public void OnEndDrag(PointerEventData eventData)
    74.     {
    75.         if (OnLeftEndDrag != null)
    76.         {
    77.             OnLeftEndDrag();
    78.         }
    79.     }
    80.  
    81. }
    82.  
     
    Avalin likes this.
  7. zheyuanzhou

    zheyuanzhou

    Joined:
    Oct 29, 2017
    Posts:
    22
    My Friend Told me to use OnMouseEneter/Exit or OnMouseOver. If my answer are not fit for you, you can choose Those default functions as well.
     
    Avalin likes this.
  8. pxdroh

    pxdroh

    Joined:
    Nov 1, 2021
    Posts:
    1
    I know this topic is old but if anyone is having this problem this can be of great help, here is my code

    Code (CSharp):
    1. private const string normalTrigger = "Normal";
    2. private const string highlightedTrigger = "Highlighted";
    3. private const string selectedTrigger = "Selected";
    4.  
    5. private bool isHighlighted = false;
    6.  
    7. private void Update()
    8. {
    9.     if (!isHighlighted)
    10.     {
    11.         if (tabController.CurrentTab != this)
    12.         {
    13.             var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
    14.  
    15.             if (stateInfo.IsName(highlightedTrigger) && !stateInfo.IsName(selectedTrigger) && !animator.IsInTransition(0))
    16.                 animator.SetTrigger(normalTrigger);
    17.         }
    18.     }
    19. }
    20.  
    21. public void OnPointerEnter(PointerEventData eventData)
    22. {
    23.     isHighlighted = true;
    24.  
    25.     if (tabController.CurrentTab != this)
    26.     {
    27.         var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
    28.  
    29.         if (stateInfo.IsName(normalTrigger) || !stateInfo.IsName(selectedTrigger))
    30.             animator.SetTrigger(highlightedTrigger);
    31.     }
    32. }
    33.  
    34. public void OnPointerExit(PointerEventData eventData)
    35. {
    36.     isHighlighted = false;          
    37. }
     
  9. GuidewireGames

    GuidewireGames

    Joined:
    Apr 20, 2017
    Posts:
    27
    I'm working on a VR menu and need to rely on OnPointer...

    I have a popup that is triggered on pointer enter of a panel. When the point enters the popup it has buttons inside of it that can trigger point exit and I'm trying to figure out how to ignore internal elements , but when leaving the popup completely it doesn't seem like OnPointerExit is trustworthy.
     
  10. ms02

    ms02

    Joined:
    Jun 8, 2020
    Posts:
    3
    @GuidewireGames you might have figured it out already, but if you uncheck the "Raycast Target" on the GO/elements that you don't want interacting with your pointer they'd stop doing so
     
  11. reinisliepins10

    reinisliepins10

    Joined:
    Sep 23, 2023
    Posts:
    1
    If someone desperately needs to check if mouse is over a button reliably, you can always just use raycasting,
    Code (CSharp):
    1. private void Update()
    2. {
    3.     RaycastHit2D hit = Physics2D.Raycast(Input.mousePosition, Vector2.zero);
    4.  
    5.     if (hit.collider != null)
    6.     {
    7.         Debug.Log("Mouse is over the button!");
    8.     }
    9.     else
    10.     {
    11.         Debug.Log("Mouse is not over the button!");
    12.     }
    13. }
    Unfortunately, it's not just OnPointerExit that sometimes doesn't fire. OnPointerEnter also doesn't work if you move your mouse too quickly, but at least that one makes sense.
     
    Last edited: Feb 26, 2024
  12. YannickZanyath

    YannickZanyath

    Joined:
    Aug 8, 2023
    Posts:
    1
    Well! This does the trick for me! Thank you very much!