Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Event System and touch controls conflict

Discussion in 'Scripting' started by Bonfi_96, Jan 7, 2018.

  1. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    I'm not really sure if this can be solved easily, but I spent the whole day trying to wrap my head around it without results.
    I'm making a mobile game: it has UI on a canvas, a 3d environment and it should have a drag gesture to rotate the camera around.

    The problem is that I want that gesture to start only if the gameobject I'm pressing on can't handle a pointer event.
    As an example, there is an ineractable object in the current 3d view:

    if I press in the 3d space, on or not on an object that can or can't handle the event I want to be able to rotate the camera,
    but when the pointer gets back up I want to do noting if there isn't any object under the pointer or the object can't handle the event while I want to handle the pointerup if the object can.

    The part where I'm having issues is to detect when I'm not pressing on an object at all or if I'm pressing on an object that can't handle a press event. Do I need to write a custom InputModule? Or maybe override the Process... methods in the StandaloneInputModule?

    I think that ideally I would like to handle the "non presses" as presses on an object that has no physical presence in the scene but can still handle the events.

    Thanks!
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Some questions for clarification..

    The UI should prevent camera movement (drag)?
    Objects in the scene should not prevent camera movement dragging?

    is that correct?
     
  3. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    Exactly, yes and yes, also just in case it's relevant, I know that unity can handle pointer on UI vs pointer on 3d gameobject. Also, thanks a lot for taking interest
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Sure, so I recently chatted in a thread about this recently. I believe the poster there chose to do a raycast when they were clicking to find the target , if applicable, and test if it was something they wanted or not (or ignore or not).
    I tried to suggest using the PointerEventData which, if the 'IsPointerOverGameObject' is true, means there has been a pointer enter event. Then, that is stored in a variable, which could be check (I'm pretty sure on this).
    However, I think the raycast is a good option, too.. Whatever seems more comfortable for you.

    Like, in your example, you'd just check if it's the UI or not can let dragging happen to move the camera if it's not.
    Otherwise, the event system could let you interact with a 3d object (however you go about that).
    If you are not using the event system for your 3d interactions, that may require the raycast instead (I assume probably yes:)).

    I'm not saying that's a full complete answer, but hopefully from it you can derive a solution.
    Since I didn't 100% understand your first post, and we assume this might/probably will work for this portion, is there anything that was left out? :)
    *obviously you should write back on this portion if it fails to do what you wanted lol
     
  5. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    That's interesting, I could use isPointerOverGameobject to solve half of my problem, if the pointer is in the emptiness of space or on a GO without events handlers it should return false (accordingly to the docs, I'll test that tomorrow) then I could handle the unwanted events one by one. I'll try tomorrow, 4am is bad for coding :3 Thanks again!
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ya, that's what I was thinking.. hopefully solve some stuff, and also allow you to do further testing if it's true (maybe).. or whatever you were thinking. Good luck testing tomorrow :)
     
  7. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    I made a quick test, isPointerOverGameobject returns true even for gameobjects without handlers, the docs said "Is the pointer with the given ID over an EventSystem object?" but it seems like any gameobject is an EventSystem object
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I believe in your case it could mean any raycast hit canvas object or any game object with a collider?
    That's what I was thinking would require some follow up to see which type the pointer is over...
     
  9. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    I'm pretty sure I have to extend the StandaloneInputModule in a way that calls events on an "InputManager" gameObject if some conditions are met. This would solve the problem from the root as the "smart part" would be the input manager itself and I wouldn't need to handle unwanted presses in every gameobject. I managed to inherit from StandaloneInputModule though I'm having trouble overriding this method even if the docs say it can be done
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    When I look that up on bitbucket it's private.
     
  11. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    But there is ProcessMouseEvent and/or ProcessMousePress in the stand alone input module.
     
  12. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    Same issue with that one, it's also protected but not virtual (I'm looking too on bitbucket on the 2017.1 branch)
     
  13. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ah Sorry :)
     
  14. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Well, this is something I always wanted to do..
    How does this work for ya?
    Code (csharp):
    1.  
    2. public class MyInputModule : StandaloneInputModule{
    3.  
    4.    public override bool IsPointerOverGameObject(int pointerId)
    5.     {
    6.         var lastPointer = GetLastPointerEventData(pointerId);
    7.         if (lastPointer != null)
    8.         {
    9.             if (lastPointer.pointerEnter != null)
    10.             {
    11.                 if (lastPointer.pointerEnter.layer == LayerMask.NameToLayer("UI")) return true;
    12.             }
    13.         }
    14.         return false;
    15.     }
    16. }
     
  15. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    This makes no distinction ; you wouldn't be able to check if you were over a non-UI object (yet) with this..
    If you needed it, you could write another. If you only cared if you were over the UI to avoid tasks, I think this would work.
     
  16. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    I just went the rogue way: copied the StandaloneInputModule source, and inherited from it using after making the methods virtual. Now if the events are not handled by anything they are sent to a specific gameobject that handles the touch controls. Also I reported the docs issue to unity hoping they'll make them virtual. Not sure if it will be a good solution on the long term :(
     
  17. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    lol okay cool that's good for now at least. :)
     
  18. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    35
    Thanks a lot for the help, it's weird that a solution that seems so stupid works really well
     
  19. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Then it's not so stupid after all :) hehe.. And you're welcome, was fun.