Search Unity

Question When are IPointerHandlers executed in the Unity life cycle?

Discussion in 'Scripting' started by jeppe79, Aug 14, 2020.

  1. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    75
    Hello,

    Studying this execution order chart:
    https://docs.unity3d.com/Manual/ExecutionOrder.html

    Where in this chart do we place the IPointerHandlers?

    I thought it was included in the Input events, but after some testing that doesn't seem to be the case.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    It will be called somewhere in that loop of the execution order you posted above.

    Since the docs for that interface don't specify when it gets called, I recommend structuring your code so that it does not matter when it gets called. In other words, do very little work in the actual handler, just store the fact that it happened in local variables, and then process it as you see fit in Update() of timing is of critical importance to you.
     
  3. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Input events is certainly what I would have guessed. What did your tests show, exactly?

    I don't see how that helps. If you don't know whether a given event happens before or after Update, then you might or might not be delaying your handling of the input until the next frame. If timing is important, that seems almost certainly worse than having uncertainty about when within a given frame it is being handled.
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    It's not documented but I suspect it might just be in the middle of Update() somewhere, triggered from the EventSystem object's Update method. You might be able to test this by creating two scripts at the extreme ends of Unity's ScriptExecutionOrder, and one pointer handler, and see if a log from the pointer handler gets printer before both of the other scripts, in the middle of them , or after both of them.

    Edit: Event System actually shows up in script execution order by default, so you can just wrap that:

    upload_2020-8-14_14-12-1.png
     

    Attached Files:

    Last edited: Aug 14, 2020
    Suddoha likes this.
  5. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,065
    Those are the legacy OnMouseXXX events, which are no longer supported by the new Input System.

    For IPointerXXX handlers, they are sent in the Input Module's Process method, which gets called by the Event System during Update.

    Which means the order of these input callbacks in regards to other Update methods is undefined. If you need explicit ordering, change it in Script Execution Order settings (you can't change the Event System's you have to change your scripts').
     
  6. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    I just ran some tests because it didn't show up in my version (2018 LTS). So my initial assumption was they'd manage it internally in order to save you from trouble - i mean, the input you receive during a frame was gathered during the last frame, if you could change its order, you'd be able to add an extra delay of another frame- that'd be unfortunate.

    Turns out that was a silly assumption. You can mess it up, the built-in event system is just running with a default seo of 0 in my version... Good to know, I'm wondering why I never cared about that before. :D
     
    PraetorBlue likes this.
  7. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    75
    My test was a flawed as it started mid life cycle and not from the beginning.

    The test was with two buttons, Button A with infront of Button B.
    Button A -> IPointerClickHandler
    Button B -> IPointerEnterHandler

    When clicking Button A a global bool is set true and the button disappears and Button B now receives the raycast.

    When OnPointerEnter in Button B triggers it executes Debug.Log("Is hovering");

    Then I had an IF statement in Update() to check if that bool was true.
    If true, Debug.Log("Bool is true");

    The resulting log was:
    1. Debug.Log("Bool is true");
    2. Debug.Log("Is hovering");


    So, it seems in this test that the IPointerHandler event cluster had already been executed and was finished when we had finished clicking the button and setting the bool true, therefore the Update log triggered first.
     
    Last edited: Aug 14, 2020
  8. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    75
    My problem was that my logic was dependent on the IPointerHandler running before Update().

    I solved it by moving my Update() logic to a Coroutine that waited for a frame with yield return null; and then to be safe I ran a yield return new WaitForEndOfFrame();
    That made sure IPointerHandler executed once before hte "update()" logic.
     
  9. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    I'd rather check the Script Execution Order in the settings (check @PraetorBlue's screenshot).
    Generally, you don't want to mess too much with it, but as the input events from the event system are already based on physical input that was collected during the previous frame, it should most-likely be processed right away before you do most of the other stuff in that frame.

    That'd be the clean solution IMO, and doesn't require extra delays of that kind... imagine you had to do that for many more scenarios just because the events are fired "arbitrarily" somewhere in between all your components..., how annoying and messy would it get with all the coroutines?
     
    jeppe79 likes this.