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
6.01k stars 2.12k forks source link

Unclear or Incorrect Behavior on Multi-Scene Projects #3601

Closed genereddick closed 5 years ago

genereddick commented 5 years ago

Overview

Also related to #3599

Currently the default configuration has two GameObjects: MixedRealityToolkit MixedRealityPlayspace

If you have a project with more than one scene, you currently have several options:

  1. Have both the and Toolkit and Playspace in each scene. Result: If you do this, the Toolkit, which has DontDestroyOnLoad (DDOL), persists across scenes and you get the errors below.

  2. Remove the Toolkit from subsequent scenes but keep the Playspace in each. Result: You get a Transform error related to the gaze object, and no cursor in the second scene.

  3. Toolkit and Playspace only in the first scene. Result: Playspace doesn't have DDOL so you have no camera and more errors in the additional scenes.

  4. Toolkit and Playspace only in the first scene. Add DDOL to Playspace. Result: Works, sort of, but makes it impossible to test scenes unless you always start with the first scene.

  5. Move Toolkit and Playspace to separate scene for Additive Loading to the current scene Result: Constant annoying, and difficult to dismiss, popup saying: There is no active Mixed Reality Toolkit in your scene! Would you like to create one now? Still getting the same gaze Transform errors as in 2 above.

  6. Move Toolkit and Playspace to separate scene for Additive Loading, Add DDOL to Playspace Result: Works with starting both on first and second scene (the popup stopped showing up though I don't know why, so this may also require adjusting the code that is checking for the existence of those objects.)

  7. Start project with Toolkit and Playspace in initial scene, additively load / remove additional scenes (per comments in #3261) Result: Works with some scripting. However, more difficult to test additional scenes as you can't just run the scene you are currently working on. Maybe there is a pattern here I'm missing though?

Digging further through the linked comments (#3246), if MRTK only supports having the Toolkit and Playspace in the initial scene -- though it makes testing additional scenes trickier -- it seems like you could do a hybrid approach, where the default behavior is 6 above, with Tookit and Playspace in init scene, and additively load / unload additional scenes.

For one-off testing of additional scenes after the first, as in 5 above, have a separate Scene (say ToolkitTestScene) with only the Toolkit & Playspace, then check for their existence on awake (in Scene 2 for example), and if not there, then additively load ToolkitTestScene. This preserves both the correct default behavior and ease of testing.

Expected Behavior

No errors. Maybe.

Actual Behavior

Errors

If Toolkit in each scene: Unable to find IMixedRealityInputSystem service. UnityEngine.Debug:LogError(Object) Microsoft.MixedReality.Toolkit.Core.Services.MixedRealityToolkit:GetService(Type, String, Boolean) (at Assets/MixedRealityToolkit/Services/MixedRealityToolkit.cs:1109)

NullReferenceException: Object reference not set to an instance of an object Microsoft.MixedReality.Toolkit.Core.Providers.GenericPointer..ctor (System.String pointerName, Microsoft.MixedReality.Toolkit.Core.Interfaces.InputSystem.IMixedRealityInputSource inputSourceParent) (at Assets/MixedRealityToolkit/Providers/GenericPointer.cs:28)

If Playspace in each scene

MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. UnityEngine.Transform.get_position () <0x18da2630 + 0x0006a> in <78121f72672f4a9b8378f38120b3de75>:0 Microsoft.MixedReality.Toolkit.Services.InputSystem.GazeProvider+InternalGazePointer.OnPreRaycast () (at Assets/MixedRealityToolkit.Services/InputSystem/GazeProvider.cs:191) Microsoft.MixedReality.Toolkit.Services.InputSystem.FocusProvider.UpdatePointer (Microsoft.MixedReality.Toolkit.Services.InputSystem.FocusProvider+PointerData pointer) (at Assets/MixedRealityToolkit.Services/InputSystem/FocusProvider.cs:597) Microsoft.MixedReality.Toolkit.Services.InputSystem.FocusProvider.UpdatePointers () (at Assets/MixedRealityToolkit.Services/InputSystem/FocusProvider.cs:568) Microsoft.MixedReality.Toolkit.Services.InputSystem.FocusProvider.Update () (at Assets/MixedRealityToolkit.Services/InputSystem/FocusProvider.cs:330) Microsoft.MixedReality.Toolkit.Core.Services.MixedRealityToolkit.UpdateAllServices () (at Assets/MixedRealityToolkit/Services/MixedRealityToolkit.cs:960) Microsoft.MixedReality.Toolkit.Core.Services.MixedRealityToolkit.Update () (at Assets/MixedRealityToolkit/Services/MixedRealityToolkit.cs:570)

Steps to reproduce

(Links to sample github project preferred) Created a base project with two scenes and a sceneloader

Unity Editor Version

2018.3.8f1

Mixed Reality Toolkit Release Version

vNext Beta 2

StephenHodgson commented 5 years ago

See my reply in https://github.com/Microsoft/MixedRealityToolkit-Unity/issues/3599#issuecomment-471687630

genereddick commented 5 years ago

@StephenHodgson Thanks, that makes sense.

I do similar, except that I placed the MRTK Camera and other assets in the additively loaded scene but also had it in the Hierarchy when working on any scene that isn't the first.

So, I expect this work flow (MRTK objects in main scene, additively load follow-on scenes) will be fine for most multi-scene projects. At least for mine. And, I think if documented shouldn't be too difficult to customize for other patterns.

david-c-kline commented 5 years ago

@genereddick, thanks for the details! this information is super helpful

genereddick commented 5 years ago

Per @StephenHodgson I've adopted his approach of having the assets in the top level scene and additively loading additional scenes and this works very well.

I think the only issue that has required changing some code is the lack of access to Camera.main from additively loaded scenes. Given that Camera.main apparently has a performance penalty (see Jetbrains article below), using FindObjectsOfType to get it once and caching it for use in loaded scenes / classes is probably a better pattern in any case.

https://support.unity3d.com/hc/en-us/articles/115000227183-Camera-main-is-slow

StephenHodgson commented 5 years ago

We have a utility specifically for this called CameraCache.Main there's also a flag in the camera options to make the camera persistent (although I'm wondering if that should actually be enabled by default)

genereddick commented 5 years ago

I think from the perspective of someone starting from scratch having the camera be persistent would be the correct default, but easily handled with documentation in either case.

Railboy commented 5 years ago

These issues should be resolved by #4035. If you're still having trouble let us know and we can re-open this.