microsoft / MixedRealityToolkit-Unity

This repository is for the legacy Mixed Reality Toolkit (MRTK) v2. For the latest version of the MRTK please visit https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity
https://aka.ms/mrtkdocs
MIT License
6k stars 2.12k forks source link

Plan of Record: Document Unity UI best practices and optimize demo scene UI layout #7719

Closed david-c-kline closed 2 years ago

david-c-kline commented 4 years ago

MRTK's support for Unity UI relies upon a potentially (up to 1.5ms) expensive API call (EventSystem.RaycastAll) per pointer. This can add up rapidly and cause the focus provider to consume significantly more CPU budget than the target for all of MRTK (~4ms).

Thanks to fantastic community feedback, we have landed on a plan to:

  1. Optimize the demo scene Unity UI usage (remove Raycast Target from non-interactable / non-background elements)
  2. Document best practices for using Unity UI and describe the performance impacts.
keveleigh commented 4 years ago

In option 2, there is a catch. Depending on the control stack, it is not ensured that the top most item is interactable (ex: text labels on buttons are not).

Do we currently check for this in the RaycastAll method?

david-c-kline commented 4 years ago

From my read of the code, that is handled by the raycast comparer in the prioritization step (which uses the collection of all results returned by the RaycastAll method).

WikkidEdd commented 4 years ago

We use Unity UI exclusively for our UI and have done a lot of investigation in to performance and can share some of our findings.

EventSystem.RaycastAll is expensive because there is no broadphase collision detection on Unity UI canvases, so it tests every UI element in the whole scene that has "Raycast Target". So the more UI elements you have the more expensive it is.

Best Practice: Turn off "Raycast Target" on everything apart from interactive elements (buttons, tick boxes, etc) and a background element which defines the shape of a panel. So text, images etc which are there just for visual should have "Raycast Target" disable. You can write simple tools to help with setting the flag as appropriate. In addition to the above best practice we have a custom graphics raycaster which uses the bounds of a canvas as a broadphase collision test. If you ensure all UI is inside a well fitted canvas, the UI elements themselves only get tested when the pointer is on the canvas.

These two approaches combined makes the UI raycast cost negligible for even very complex UIs.

One other thing to note is that default number of segments for a Line Pointer is 2 (at least in MRTK v2.2) for what is essentially a straight line, that's 2 times as many raycasts as are needed.

As for direct feedback to your suggestion: I would favour communication of best practices over magic options that can have undesirable and often confusing side effects. Ignore all Unity UI - If UI is "visual only" then the Graphics Raycaster can be removed from the canvas and you'd have no cost. Similar to your suggestion though, this would result in no indication that the cursor on the UI, so disabling all raycast targets apart from a single background/panel element would be better practice. Return the top most item - If you have enough information to use this option without running in to the cons, then you probably have enough information to follow the best practices outlined above. If you don't have enough information, you're just inviting inconsistent behaviour and not knowing why.

tank-t-bird commented 4 years ago

Adding to what @WikkidEdd has noted above, I suggest making sure that the user understands the Raycast Target and Graphics Raycaster costs as explained here.

david-c-kline commented 4 years ago

@WikkidEdd and @tank-t-bird, thank you for the input! This is fantastic feedback! From what you describe, the best approach is likely to expand our documentation and provide a link to it from the Input System inspector UI.

KevinKennedy commented 4 years ago

Could a check be added to the Optimize Window to call out when canvas UI has unneeded Raycast Targets?

david-c-kline commented 4 years ago

@KevinKennedy, I like the idea. It would conceivably have a list of known non-interactable elements and check to see if any of them have RaycastTarget enabled.

genereddick commented 4 years ago

Better documentation would be helpful on setting up both Unity UI as well as configuring MRTK UI elements with Screen Space Overlay as World Space often isn't a good experience on mobile.

stale[bot] commented 2 years ago

This issue has been marked as stale by an automated process because it has not had any recent activity. It will be automatically closed in 30 days if no further activity occurs. If this is still an issue please add a new comment with more recent details and repro steps.