Search Unity

onmouseover logic with new input system

Discussion in 'Input System' started by wtetotew, Jun 15, 2020.

  1. wtetotew

    wtetotew

    Joined:
    Apr 12, 2020
    Posts:
    68
    I'm a bit lost with the new input system.
    What would be the simple way to reproduce this behaviour with the new system:

    Code (CSharp):
    1. public class OnMouseOverScript : MonoBehaviour
    2. {
    3.  
    4.         public void OnMouseOver()
    5.         {
    6.             //If your mouse hovers over the GameObject with the script attached, output this message
    7.             Debug.Log("Mouse is over GameObject.");
    8.         if (Input.GetMouseButtonDown(0))
    9.         {
    10.             print("dedans");
    11.         }
    12.     }
    13.     }
    I have set a Press (mouse] action in a "gameplay" action map.
    I have put a sprite renderer and a collider on the Gameobject.
    I have also put a player input component on the same gameobject (set the "actions" and "default map")

    but from there, I'm a bit lost. How can I, for instance, deactivate the game object only if I'm over it (by pressing the mouse button down like customized in "Actions")?
     
    GrayedFox likes this.
  2. One way (of many) to do, like this, mockup script (so you need to adapt the idea):
    Code (CSharp):
    1. [...]
    2.  
    3. class WhateverMouseOver : MonoBehaviour
    4. {
    5. [...]
    6.     private boolean hovering = false;
    7.  
    8. [...]
    9.     private void Awake()
    10.     {
    11.         whatEverInputAction.performed += DoTheThing;
    12.     }
    13.  
    14.     private void DoTheThing(InputBlaBlaContext ctx)
    15.     {
    16.         if (hovering)
    17.             Debug.Log("Hovered and actioned together!");
    18.     }
    19.  
    20.     private void OnMouseOver()
    21.     {
    22.          hovering = true;
    23.     }
    24.     private void OnMouseOut()
    25.     {
    26.          hovering = false;
    27.     }
    28.  
    29.  
    30. }
     
  3. wtetotew

    wtetotew

    Joined:
    Apr 12, 2020
    Posts:
    68
    Thanks for your answer. That make sens.

    I want to make a simple game where a gameobject appear (become active) and I get score point when I click/touch it.
    So for my purpose, isn't the new input system more complicated eventually?

    I tried to find the simpliest way) (but also future proof) and read about Event system events like
    IpointerDownHandler. Wouldn't it be appropriate for my case?

    Thank you very much!

    A noobie.
     
  4. It is something you need to decide. If you want to customize your controls, the new Input System is mostly the way going forward.
    If you just want to throw a quick Input.GetMouseButton(0) at your code and hope for the best, then it doesn't matter.
    It is up to you if you want to create things right or seemingly fast but less robust when you change your mind. We can't decide this for you.

    One advice though: forget "future proof". There is no such thing. You need to concentrate on what you want to do right now. You do the thing exactly, not less but not more either. When you have the need to change something come back to it and change it. But do not attempt to "future proof" your stuff. 99% of the time you won't need it because you will want somewhat else or on other ways.
     
    inai likes this.
  5. wtetotew

    wtetotew

    Joined:
    Apr 12, 2020
    Posts:
    68
    Ok I understand what you say. I think I want to try the new input system but I watched many tutorial and everytime it looks different so I'm a bit lost.

    For instance, in your mockup script:

    1/I don't understand this line:
    Code (CSharp):
    1. private void DoTheThing(InputBlaBlaContext ctx)
    What should I put in the bracket? I don't get what is InputBlablacontext and ctx argument.


    2/ Also, first, I have to declare the input action right? like this (I named them Controls):

    Code (CSharp):
    1. private Controls controls;

    3/ Do I have to put this line as well?:

    Code (CSharp):
    1. private void OnEnable()
    2.     {
    3.         controls.Enable();
    4.     }
    5.  
    6. private void OnDisable()
    7.     {
    8.         controls.Disable();
    9.     }
    4/ And
    Code (CSharp):
    1. private void Awake()
    2.     {
    3.         controls = new Controls();
    4.         controls.GamePlay.Hit.performed += _ => DoTheThing();
    5.     }
    in your mockup it's like that:
    Code (CSharp):
    1. private void Awake()
    2.     {
    3.         whatEverInputAction.performed += DoTheThing;
    4.     }
    5.  
    should I keep it like that (and only changing "whateverAction" to my action)?

    5/ Lastly I suppose it's not possible but I was wondering:

    could I write
    Code (CSharp):
    1. if (onmouseover())
    2.    Debug.Log("It works")
    instead of
    Code (CSharp):
    1.   if (hovering)
    2.             Debug.Log("it works");
    with a boolean variable?

    Excuse me for all these questions, probably obvious for you but as I already said, I'm a beginner.

    Have a nice day and thanks for your help!!
     
  6. The fastest and safest way to learn how to do things is this:
    - open your Unity Hub
    - create a new, empty project on the Unity version you're using
    - when the empty project opened in Unity, install the Input system as normal
    - then go back to the package manager, open up the samples section
    - select what samples you want to learn
    - import them into your test project
    - play them, see how they work, look at the code what they have done

    answwer.png
     
    Estema_TheWoz likes this.
  7. wtetotew

    wtetotew

    Joined:
    Apr 12, 2020
    Posts:
    68
    Thanks this helped me.

    but I still don't understand this line:

    1. private void DoTheThing(InputBlaBlaContext ctx)
    InputBlablacontext and ctx argument are related to interactions right?
    Since I only need to press the left mouse button why should I use context?

    Also it's not really in the topic but I can't find answer to that question:
    could I write

    1. if (onmouseover())
    2. Debug.Log("It works")
    ?
     
  8. I always forget the type of the context, look it up. It's InputAction.<something>Context. You can find it just as easily than I would.

    You could write. But I don't understand why would you introduce a method call where a private variable is perfect?
     
  9. wtetotew

    wtetotew

    Joined:
    Apr 12, 2020
    Posts:
    68
    Excuse me, English is not my Native language and it seems there is a misunderstanding here.

    I don't ask for the type of the context but what is context. What is for? Why is it used for and how?

    From what I think I have understand it has something to do with how you interact with the hardware, like holding a button instead of just pressing it.

    But if it's right, why do I have to use context, why I cannot just type "private void DoTheThing()" in my particular case, which is just one press on the mouse button to do something on a Game object?

    Because if typing all this:

    Code (CSharp):
    1. private bool hovering = false;
    2.  
    3. private void DoTheThing(InputBlaBlaContext ctx)
    4.     {
    5.         if (hovering)
    6.             Debug.Log("Hovered and actioned together!");
    7.     }
    8. private void OnMouseOver()
    9.     {
    10.         hovering = true;
    11.     }
    12.     private void OnMouseOut()
    13.     {
    14.         hovering = false;
    15.     }
    Is equivalent to

    Code (CSharp):
    1. private void DoTheThing(InputBlaBlaContext ctx)
    2.     {
    3.        if (onmouseover())Debug.Log("It works")
    4. )
    5.             Debug.Log("Hovered and actioned together!");
    6.     }
    The later is far simplier or am I missing something?
     
  10. It carries information what happened during the action. See the InputSystem documentation what is in the context parameter.

    No, it isn't. OnMouseOver and OnMouseExit (sorry, not OnMouseOut) are Unity Magic Methods. They get called when your mouse hovering over gameobjects or when your mouse stops hovering over (leave).
    https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseOver.html
    https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseExit.html
     
  11. wtetotew

    wtetotew

    Joined:
    Apr 12, 2020
    Posts:
    68
    Yes that is what I wrote there:
    And that is why I asked:
    I already read the documentation.

    But eventually I think I will just use the old way because the new input system is far too complicated for me.
     
  12. AlexSabo

    AlexSabo

    Joined:
    Mar 31, 2020
    Posts:
    1
    Last edited: Jul 31, 2020
  13. GrayedFox

    GrayedFox

    Joined:
    Jan 28, 2014
    Posts:
    70
    Hey, stumbled upon here looking for a way to emulate OnMouseOver or OnMouseEnter. Is there any way to get the game object that triggers the UI InputAction event?

    Using the following code I can get a mouse-in/over event (that repeatedly fires so long as the mouse pointer remains in the button's area):

    Code (CSharp):
    1.     public void OnPoint(InputAction.CallbackContext context)
    2.     {
    3.         Debug.Log("Point");
    4.     }
    The problem is, I need to know which game object caused that OnPoint event (so I can differentiate it). Does anyone have an idea how to do this?
     
  14. GrayedFox

    GrayedFox

    Joined:
    Jan 28, 2014
    Posts:
    70
    I figured it out. By implementing IPointerEventHandler one can get the gameObject that triggers an enter event:

    Code (CSharp):
    1. public class MenuNav : MainMenu, IPointerEnterHandler
    2. {
    3.     public void OnPointerEnter(PointerEventData eventData)
    4.     {
    5.         Debug.Log("PointerEnter");
    6.         Debug.Log(eventData.pointerEnter);
    7.         OnPoint(eventData.pointerEnter);
    8.     }
    9. }
    I ended up removing the Point UI input action from the UI action map completely in favour of calling OnPoint manually.
     
  15. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    That's really nasty, hiding away a major bug as a 'limitation'.

    The core docs for MonoBehaviour are now wrong - they state unambiguously e.g.:

    "OnMouseDown is called when the user has pressed the mouse button while over the Collider."

    ...which is a lie: Unity Input team have removed that functionality - and they didn't bother to update the docs. It feels like they wanted to sweep this set of bugs under the carpet and avoid finishing their implementation.

    I've filed a bug against this (probably a dupe of many many other people filing the same bug), and suggested:
    1. Update the MonoBehavioru docs (I mean ... this is trivial for them to do. But I guess no-one wants to admit in public that they broke MonoBehaviour ... if they did that, someone might force them to fix it too!)
    2. Add a compile-time warning/error if OnMouse* methods are detected without #IF ENABLE_LEGACY_INPUT -- because without that they are (now) errors, and build should fail.

    EDIT: it's Case 1356447. Currently no reply from Unity > 1 month later.
     
    Last edited: Sep 7, 2021
    VenetianFox, kbkev78, mgear and 3 others like this.
  16. Quckers

    Quckers

    Joined:
    Oct 9, 2019
    Posts:
    1
    Just leaving this here since this thread is the one I am across the most often while searching for an alternative to onmouseover. Hopefully it help someone.

    Normally IPointerEnterHandler on a gameobjectis a sufficient replacement, but there are rare cases where you really want the onmouseover behaviour.

    My use case was making 2d game with tilemap with camera tilted 45 degrees. Trying to find the current mouse over cell. Since tilemap use tilemap collider 2d, IPointerEnterHandler is not practical because tilemap collider 2d merges all cells together. Physics.Raycast dont work because of 2d colliders. Since the camera is rotated, Physics2D.Raycast doesnt seem to give the correct result. Eventsystem combined with InputSystemUIInputModule should work since it already done the work to figure out how to do the raycast correctly, except there is no IPointerOverHandler / IPointerHoverHandler interface.

    My current solution for it is rebind scroll wheel input in InputSystemUIInputModule to pointer and use IScrollHandler for onmouseover. It is not the most obvious solution to the problem, but works because this way you get OnScroll callback when you move your mouse which contains a raycast you can use to get world coordinate.

    A IPointerHoverHandler interface would be really useful.
     
    Faucheur_de_chattons likes this.
  17. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    Update: I got a reply to my bugreport:

    "We actually know about this issue and are tracking it as a feature request. Unfortunately, I cannot provide an Issue Tracker link, as this bug is only tracked internally."

    I do not know whether "only tracked internally" means "...i.e. no-one's working on it, and there's nothing to make a team be held accountable for working on it" vs means "...i.e. it's a high priority thing that affects us too! So we're definitely gonna fix it, relatively soon" :)
     
  18. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    I asked them for an update. It's been 6 months - the Unity team marked this as "closed" but it's unclear whether that's because they fixed it and forgot to tell anyone, or because they don't want to fix it so are closing the bugs to prevent anyone knowing the bugs exist.
     
  19. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    QA update: they'll update status in this thread (hi!).

    Disappointingly the official docs are still wrong. In 6 months I think someone could at least have edited some HTML and added "this no longer works in any version of Unity that uses the new Input System". It's just some text.
     
    Mnemotic likes this.
  20. owen_proto

    owen_proto

    Joined:
    Mar 18, 2018
    Posts:
    120
    bump. this missing feature is a complete bummer. i don't think there's anything that reasonably replaces OnMouseExit without writing something really silly and ugly. this is such a fundamental thing. :(
     
  21. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    I've heard nothing since February. So that's almost a year since the bug was filed, no progress.
     
  22. owen_proto

    owen_proto

    Joined:
    Mar 18, 2018
    Posts:
    120
    i have a couple of solutions:

    1) you can attach a PhysicsRaycaster component to your camera and then implement the IPointerEnterHandler/IPointerExitHandler/IPointerClickHandler etc. interfaces in your script. also make sure to have an event system somewhere in your scene.

    2) i wrote a script that reimplements functionality to call the MonoBehaviour.OnMouse events (Down, Drag, Enter, Exit, Over, Up, UpButton). you can place it on any GameObject in the scene and it should just work. i also wrote it so that it should be easy to replace Mouse.current with input actions if you want.
     
    Last edited: Jun 29, 2022
  23. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    Personally I re-wrote the broken bits of Unity's 'new' Input system and fixed it - it's just one of the bugs in Input they don't have the time/energy/motivation to work on. But I still want it fixed by Unity because they shouldn't be making eveyrone else work around their bugs. And they definitely shouldn't be breaking core APIs simply because they didn't test / think about their code before launching it.
     
  24. Faucheur_de_chattons

    Faucheur_de_chattons

    Joined:
    Sep 4, 2017
    Posts:
    3
    Thanks for pointing that out I just had the exact same issue, it saved me some frustrating hours. Another hacky solution is to use 3D colliders in that case.