Search Unity

EventSystem unexpecteldy calling IPointerExit in 2021.3.1f1

Discussion in 'UGUI & TextMesh Pro' started by Damien-Mayance, Apr 28, 2022.

  1. Damien-Mayance

    Damien-Mayance

    Joined:
    Sep 17, 2013
    Posts:
    11
    Hello, we updated Unity on the latest LTS and we have a very strange behaviour with the EventSystem.

    Here's our hieraarchy:

    GameObject -> Script with IPointer Enter/Exit Handler
    + child Image 1 : raycast on
    + child Image (GameObject off) 2 : raycast on
    + child TextMeshPro : raycast on

    In 2021.2.7f1 : script receive the OnPointerEnter() callback. We enable Image 2 GO. Nothing happens until cursor leaves the GameObject: expected behaviour.

    In 2021.3.1f1 : script receive the OnPointerEnter() callback. We enable Image 2 GO. Next frame, the EventSystem calls OnPointerExit() on the script. But the cursor didn't move.

    Screenshot for configuration joined.

    What is happening?
     

    Attached Files:

  2. Damien-Mayance

    Damien-Mayance

    Joined:
    Sep 17, 2013
    Posts:
    11
  3. RaventurnPatrick

    RaventurnPatrick

    Joined:
    Aug 9, 2011
    Posts:
    250
    I think you will need to open a new bug report with a repro sample.
    Bug reports that are marked as fixed are unlikely to be re-opened by Unity.
     
  4. Damien-Mayance

    Damien-Mayance

    Joined:
    Sep 17, 2013
    Posts:
    11
  5. Damien-Mayance

    Damien-Mayance

    Joined:
    Sep 17, 2013
    Posts:
    11
    Can at least someone from Unity confirm if this is the nex expected behaiour?
    This would be in total contradiction with the previous bug tracker report,but, well...
     
  6. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    602
    Recently got surprised by this trying do some animated buttons. Not wanting to dig deeper into this as a quick workaround I disabled raycast target for child elements. This is fine if child elements are fully within bounds of parent, but would be more problematic if child popped out of the parent bounds.

    This post encouraged me to do a bit more experiements. It seems that enter/exit behavior is somewhat inconsistent even when child isn't dynamically enabled or disabled. My testcase consists two square images one parented to first so that you can easily mouse over them in any order.
    O -> outside all images
    P -> mouse inside parent
    P+C -> mouse in the part where parent and child overlaps
    C -> mouse in the child part
    a.1) event listeners on parent, start with parent
    *) O -> nothing (as expected)
    *) P -> "enter Parent"
    *) P+C -> "exit Parent"
    *) C -> nothing
    *) O -> nothing
    a.2) event listeners on parent, start with child
    *) O -> nothing (as expected)
    *) C -> "enter Parent" differs from previous case !
    *) P+C -> nothing
    *) P -> "enter Parent" entering parent twice !
    *) O -> "exit Parent", "exit Parent" exiting parent twice !

    If the child is considered as part of parent mouse area (which would be reasonable) then In case a.1) I would expect "exit Parent" to happen during C->O transition not P->P+C. If child isn't part of parent mouse area there shouldn't be "enter Parent" during O->C transition. Entering same object twice without any exits, and afterwards exiting twice seems wrong.

    If there is event handler on parent and child I get following.

    b.1) event listener on parent and child, start with parent
    *) O -> nothing (as expected)
    *) P -> "enter Parent"
    *) P+C -> "exit Parent", "enter Child"
    *) C -> nothing
    *) O -> "exit Child"

    b.2) event listener on parent and child, start with child
    *) O -> nothing (as expected)
    *) C -> "enter Child", "enter Parent"
    *) P+C -> nothing
    *) P -> "exit Child", "enter Parent" entering parent second time !
    *) O -> "exit Parent", "exit Parent" exiting parent twice !

    I also tried a few cases where child is hidden by default and enabled when hovering parent, all of them resulting in child flickering which matches with "exit parent" behavior during P->C transition observed before. Tested both by enabling using
    GameObject.SetActive(true)

    and
    Image.enabled = true


    Tests where done using Unity 2021.3.2, but It probably also applies to 2021.3.1, since I had to apply workaround for animated buttons there.
     
    Last edited: May 9, 2022
    Damien-Mayance likes this.
  7. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    602
    This also ruins "highlighted" behavior for simple button with color tint transition and child image representing custom icon . Similar thing might happen with text but didn't check that yet, because I wanted to keep my test project lean without extra packages and files (that includes textmesh pro).
     
    Damien-Mayance likes this.
  8. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    602
    With Unity 2020.3.34 results look more reasonable to me: a.1 and a.2 cases are symetric with each other, there is no double entering or exiting.

    a.1) event listeners on parent, start with parent
    *) O -> nothing (as expected)
    *) P -> "enter Parent"
    *) P+C -> nothing
    *) C -> nothing
    *) O -> "exit Parent"

    a.2) event listeners on parent, start with child
    *) O -> nothing (as expected)
    *) C -> "enter Parent"
    *) P+C -> nothing
    *) P ->
    *) O -> "exit Parent"

    b.1) event listener on parent and child, start with parent
    *) O -> nothing (as expected)
    *) P -> "enter Parent"
    *) P+C -> "enter Child"
    *) C -> nothing
    *) O -> "exit Parent", "exit Child"

    b.2) event listener on parent and child, start with child
    *) O -> nothing (as expected)
    *) C -> "enter Child", "enter Parent"
    *) P+C -> nothing
    *) P -> "exit Child"
    *) O -> "exit Parent"
     
    Damien-Mayance likes this.
  9. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    602
    Just found out about fullyExited and reentered from https://issuetracker.unity3d.com/is...it-event-calls-when-hovering-over-ui-elements that makes the output slightly less weird. But whether there is a reasonable way for properly handling the new events remains questionable, as pointed out in that issue even Unity components fail to deal with it.

    In theory some of the cases broken by these changes could be handled by looking at those flags (builtin unity components don't do it), but there are also case where it doesn't seem to be possible. Code seems to be assuming that child is strictly smaller than parent, and between exiting from child and exiting combined shape cursor will always reenter the parent. That is not the case if child is partially outside parent, and maybe even if child is on edge or near edge and you are moving cursor quickly.
     
    Damien-Mayance likes this.
  10. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    602
    Damien-Mayance likes this.
  11. RoxanneUnity

    RoxanneUnity

    Unity Technologies

    Joined:
    May 17, 2022
    Posts:
    7
    Hello, we are aware of the issues this "fix" is bringing. The new fix makes it possible to have whichever behavior you wish - for example, highlight the parent or not when hovering a child element. However, we see now that a lot of people depended on the previous behavior and for them to keep it that way they need to change their project (disable raycast target) and/or add some code.

    We are looking for a new solution that will have the new flexibility, but will fallback on the old behavior by default.

    Thank you for your feedback, it's always appreciated. We will keep you updated once the new solution is ready.
     
    tbg10101_ likes this.
  12. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    602
    @unity_04C95A20CFE4756B885D What about the case where PointerExit{fullyExited=true} is never called? Once I learned about fullyExited and reenter I assumed that ignoring PointerEnter events with
    reenter=true
    and exit events with
    fullyExited=false
    would produce the old behavior, it almost does but there are some exceptions.

    If you do transitions O->C->P->C->O there is a pointer exit event for parent with fullyExited=true during C->O transition (this makes sense). But if you enter the object parent first O->P->C->O there is no pointer exit event with fullyExited=true during C->O transition.

    For enter/exit events to be usable I would expect it to have these two properties:
    • Enter{reenter=false}
      should be fully symmetrical with
      Exit{fullyExited=true}
      , this means whenever moving between two areas produce
      Enter{reenter=false}
      event, opposite movement should produce
      Exit[fullyExited=true}
      event
    • If moving between pair of areas produce an enter or exit event, it should do it consistently regardless of mouse movement sequence that was done before
    • Enter{reenter=true}
      is symetrical with
      Exit{fullyExited=false}
      , this seems to be working fine at the moment
    Currently the new version don't have the first two properties property which seems to be more of a bug in the way reenter/fullyExited flags are implemented.
     
  13. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    602
    One more property to consider is whether PointerEnter=+1, PointerExit=-1, events add up to 0. This may seem like desirable property but it has a couple of problems. The rules can be slightly fudged depending on how you count internal transitions.

    Currently when exiting from parent there can be 2 exit events with fullyExited=true. This partially makes sense since there where 2 enter events (one with reenter and one without), but at the same time it's slightly confusing since the two exit events are identical and there is no way to tell that 2 exit events correspond to two different kind of enter events.


    Number of internal transitions isn't guaranteed to be even number, this makes it problematic to balance out enter and exit events. Currently it's somewhat "solved" by having no exit transition for C->O when doing O--(enter)->P--(exit)->C->O . Although lack of exit event during C->O transition in may opinion isn't a worthwhile tradeoffs for the sake of balancing events.

    A couple of different approaches to maintain balanced enter and exit events:
    • Accept the fact that number of internal transitions can be either even or odd and ignore them when keeping balance. Count only
      Exit{fullyExited=true} 
      and
      Enter{reenter=false}
    • When generating
      Exit{fullyExited=false}
      also generate a
      Enter{pointerEnter=child}
      event. Any code which is only interested in events for parent but not children, needs to handle it anyway during O->C transition for O->C->P->O. This would allow doing
      Exit{fullyExited=true}
      later while keeping enter and exit events somewhat balanced. One downside is that events for O->P->C->O and O->C->P->O aren't exactly symetrical, unless you also move one of the 2 exit events for O->C->P->O from P->O to C->P.
    • Completely different aproach whould be rethinking the labeling of "reenter" and "fullyExited" flags. And instead having single boolean for "root/combined shape" . It would make the process of filtering relevant events much easier. Single boolean regardless of enter or exit events instead of current new aproach requiring to check 2 booleans + object property (fullyExited, reenter, pointerEnter). It also makes slightly clearer what the expected events for sequence of mouse movements should be. O->P->P+C->C->O should generate Enter{root=false}, Enter{root=true}, Exit{root=true}, Exit{root = false} . And when doing mouse movement in opposite direction O->C->P+C->P->O, Enter{root=false}, Enter{root=true}, Exit{root=true}, Exit{root=false}. Only somewhat unclear part is whether Exit{root=true} should happen during P->P+C transition or during P+C->C, both have their usecases.
     
  14. Simpowitch

    Simpowitch

    Joined:
    Nov 13, 2018
    Posts:
    14
    @unity_04C95A20CFE4756B885D Thank you! We in LTS 2021.3.2f1 are happy to hear this will be fixed (support for the old behaviour) and are waiting for a new version.
     
  15. anthonyatmerri

    anthonyatmerri

    Joined:
    Jun 3, 2020
    Posts:
    7
    @unity_04C95A20CFE4756B885D

    Any update or timeline on this? We are depending on this logic working correctly and as karliss pointed out, exiting the entire object from the child does not trigger a full exit = true.
     
  16. tbg10101_

    tbg10101_

    Joined:
    Mar 13, 2011
    Posts:
    192
    Just saw this in the 2021.3.6 release notes:
     
    andrewpey and karliss_coldwild like this.