Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Force OnPointerEnter without moving mouse

Discussion in 'Scripting' started by Giustitia, Jun 6, 2021.

  1. Giustitia

    Giustitia

    Joined:
    Oct 26, 2015
    Posts:
    113
    Hello!

    There is a way to force check "onEnter" and "onExit" UI events from code? For example, I have a Grid Layout Group with buttons that become red when mouse gose over them and get deleted on click. The problem is that if I delete a button, the new button that goes under the mouse (since the Grid Layout Group do his job) doesn't become red until I move the mouse.

    Any solution? :D
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    This totally works for me just fine. Are you sure something else isn't happening?

    I tested:

    method 1. button has a
    Destroy(gameObject);
    script to destroy on click... works fine when the new button slides into place, highlighted and all, no mouse motion

    method 2. a script that waits 2 seconds, then deletes the button WITHOUT clicking... works fine too. Mouse hovers with no motion, and highlight is updated.

    I tested in Unity 2021 and then went back to Unity 5 and same-same-same.

    Maybe try Disable / Enable the GridLayoutGroup GameObject?
     
    Giustitia likes this.
  3. Giustitia

    Giustitia

    Joined:
    Oct 26, 2015
    Posts:
    113
    Hey thanks for the answer. I'm using Unity 2021 too, and also the new input system (don't know if keep calling it "new" make any sense ). Did you tried with the new or the old input system?

    Anyways, since on your pc it works I'll surely check if there is some kind of problem with the grid layout or even with the input system
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    I'm not using the new input system. I don't think that's a factor. I am hooking the button event and that works, and then like I said I tried the 2-second-to-destroy timer and that works.

    I think there is only one version of the UI too: version 1.0.0

    Try maybe using a coroutine to delay the Destroy() by one frame?
     
    Giustitia likes this.
  5. Giustitia

    Giustitia

    Joined:
    Oct 26, 2015
    Posts:
    113
    Already tested using delays or even moving it away without destroying with no results.

    Anyways, once I find the problem I'll come back to tell how I solved it :D
     
    Kurt-Dekker likes this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    I retract my above statement. The New Input System IS the problem here.

    I have reproduced your error trivially, both with click-to-destroy and timed-destroy while hovering.

    Steps to reproduce: add the New Input system, upgrade the EventSystem (as per the provided clickbox) and now when the mouse is hovering over a button and a new one moves under it, it DOES NOT re-highlight.

    Well, one more reason to delay using the new input system until they fix stuff like this. Perhaps there's a New Input System "UPDATE ALL INPUT" message we're supposed to ping?

    If not, I suggest you file a bug. This is definitely a bug, even if there is some kind of wiggy-wonky work-around.

    Allow me to mount my soapbox for a brief moment: This is the kinda crap that drives me insane with UI engineering that blindly and mindlessly strives so hard to become "event driven" and "message driven," generally with the stated goals of simplicity and performance.

    If you doubt me, spend some time using Android... it has more whacky weird edge-case UI focus and response failures than any other operating system in history, and if you dig down into why, it's all because they didn't want to just poll a global input state facility, DESPITE there only being one touch surface.

    All that "event driven" means is "Now there are TEN TIMES more places for weird UI edge case bugs to appear."

    And last I checked, gathering input has NEVER been a performance bottleneck on ANY system, EVER. Not even once in the history of mankind. Even smoke signals didn't have a performance bottleneck.

    /End soapbox. Carry on.
     
  7. Giustitia

    Giustitia

    Joined:
    Oct 26, 2015
    Posts:
    113
    Ok nice, just tested without Grid Layout and problem is still there. I came here while a new project was being created to test with the old input system and saw your post :D

    Anyways, I'll sped a little more time trying to figure out a "clean" solution before opening a bug report. Thanks for your time, appreciate it so much :D
     
    Kurt-Dekker likes this.
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    Giustitia likes this.
  9. Giustitia

    Giustitia

    Joined:
    Oct 26, 2015
    Posts:
    113
    Many many thanks. I'll wait for a saving answer. Now let's back to work :p
     
  10. vejab

    vejab

    Joined:
    Dec 21, 2021
    Posts:
    85
    Is there still no solution?
    When a button appears under the pointer, it doesn't trigger the "onHover" but moving the mouse even one pixel is enough to trigger it. There has to be a way to force the "onHover" like making the game thinks the pointer disappeared and reappeared or that the mouse just moved even though it didn't.
     
  11. legendaryaszu

    legendaryaszu

    Joined:
    Jun 29, 2014
    Posts:
    3
    Hello!
    Facing this issue today, and since I didn't find any concrete answer, here's a simple workaround that solved it to me:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.InputSystem;
    4. using UnityEngine.InputSystem.LowLevel;
    5.  
    6. public class ForceUpdateMouse : MonoBehaviour
    7. {
    8. #if UNITY_STANDALONE && !ENABLE_LEGACY_INPUT_MANAGER
    9.     //This was the lowest working value when testing
    10.     const float displacement = .0001f;
    11.     int dir = 1;
    12.     void Update()
    13.     {
    14.         //Retrieve current mouse state
    15.         Mouse.current.CopyState(out MouseState state);
    16.         //Change the position
    17.         state.position += displacement * dir * Vector2.right;
    18.         //invert the direction so we can return the same amount in the next frame
    19.         dir *= -1;
    20.         //Change the state
    21.         InputState.Change(Mouse.current, state);
    22.     }
    23. #endif
    24. }
    25.  
    My idea is to force a very small change to the mouse's position and then go back each frame, so the events are fired even if the player doesn't actually move it.