Search Unity

  1. Read here for Unity's latest plans on OpenXR.
    Dismiss Notice

Help Wanted Reset MARS

Discussion in 'Unity MARS' started by EarMaster, Sep 30, 2020.

  1. EarMaster

    EarMaster

    Joined:
    Mar 7, 2013
    Posts:
    38
    I was wondering what the intended way is to restart a MARS session during runtime. Let's say I have a user using MARS, then doing something else (inside my app or outside of it) and when he returns I want the system to react as if he hasn't used MARS before.

    Is it safe to just deactivate all MARS related behaviours and reactivate them or is there something else that needs to be done?
     
  2. mtschoen

    mtschoen

    Unity Technologies

    Joined:
    Aug 16, 2016
    Posts:
    139
    Hi there! There are two things you might want to pause or reset. One is AR features like plane scanning and point cloud update, and the other is the state of the proxies and the MARS query system.

    As you guessed, the way to reset the state of your queries is to deactivate your MARS proxy objects. As for the AR features, you can call the Start/Stop methods on interfaces like `IUsesPlaneFinding` as well as Reset on the `IUsesSessionControl` interface to reset the session origin and all AR data. Reset may not be exactly what you want, though, because the individual AR systems will still be running and, for example, detecting planes.

    Another surefire way to reset everything is to just switch scenes. MARS is set up to reload all of its modules and systems when you switch scenes, either at runtime or in the Editor. Of course, this comes with a visible transition which is best hidden by a full screen menu or some other visible transition that hides the camera feed.

    Hope this helps! :D
     
    EarMaster likes this.
  3. EarMaster

    EarMaster

    Joined:
    Mar 7, 2013
    Posts:
    38
    Switching scenes is not an option unfortunately. I tried to call the static ResetSession or Start/StopDetectingPlanes function, but they require an object as parameter, but I don't know which object to pass.
     
  4. mtschoen

    mtschoen

    Unity Technologies

    Joined:
    Aug 16, 2016
    Posts:
    139
    The intent is that you use them as extension methods. Our system will hook up scene objects to their functionality provider, and you can call `this.Foo()`

    In your case, you would just add a MonoBehaviour to your scene that looks something like this:
    Code (CSharp):
    1. using System;
    2. using TMPro;
    3. using Unity.MARS.Providers;
    4. using Unity.MARS.Settings;
    5. using Unity.XRTools.ModuleLoader;
    6. using UnityEngine;
    7. using UnityEngine.Events;
    8.  
    9. namespace Unity.MARS
    10. {
    11.     public class SessionUI : MonoBehaviour, IUsesFunctionalityInjection
    12.     {
    13.         class Subscriber : IUsesSessionControl, IUsesPointCloud, IUsesPlaneFinding, IUsesMarkerTracking
    14.         {
    15.             IProvidesSessionControl IFunctionalitySubscriber<IProvidesSessionControl>.provider { get; set; }
    16.             IProvidesPointCloud IFunctionalitySubscriber<IProvidesPointCloud>.provider { get; set; }
    17.             IProvidesPlaneFinding IFunctionalitySubscriber<IProvidesPlaneFinding>.provider { get; set; }
    18.             IProvidesMarkerTracking IFunctionalitySubscriber<IProvidesMarkerTracking>.provider { get; set; }
    19.         }
    20.  
    21.         [Serializable]
    22.         class PauseEvent : UnityEvent<bool> { }
    23.  
    24.         const string k_PauseText = "Pause";
    25.         const string k_ResumeText = "Resume";
    26.  
    27. #pragma warning disable 649
    28.         [SerializeField]
    29.         TextMeshProUGUI m_Text;
    30. #pragma warning restore 649
    31.  
    32.         readonly Subscriber m_Subscriber = new Subscriber();
    33.  
    34.         IProvidesFunctionalityInjection IFunctionalitySubscriber<IProvidesFunctionalityInjection>.provider { get; set; }
    35.  
    36.         void Start()
    37.         {
    38.             m_Text.text = MARSCore.instance.paused ? k_ResumeText : k_PauseText;
    39.             this.InjectFunctionalitySingle(m_Subscriber);
    40.         }
    41.  
    42.         public void TogglePaused()
    43.         {
    44.             var paused = MARSCore.instance.paused;
    45.             if (paused)
    46.             {
    47.                 m_Text.text = k_PauseText;
    48.                 paused = false;
    49.             }
    50.             else
    51.             {
    52.                 m_Text.text = k_ResumeText;
    53.                 paused = true;
    54.             }
    55.  
    56.             MARSCore.instance.paused = paused;
    57.             if (paused)
    58.             {
    59.                 if (m_Subscriber.HasProvider<IProvidesPointCloud>())
    60.                     m_Subscriber.StopDetectingPoints();
    61.  
    62.                 if (m_Subscriber.HasProvider<IProvidesPlaneFinding>())
    63.                     m_Subscriber.StopDetectingPlanes();
    64.  
    65.                 if (m_Subscriber.HasProvider<IProvidesMarkerTracking>())
    66.                     m_Subscriber.StopTrackingMarkers();
    67.             }
    68.             else
    69.             {
    70.                 if (m_Subscriber.HasProvider<IProvidesPointCloud>())
    71.                     m_Subscriber.StartDetectingPoints();
    72.  
    73.                 if (m_Subscriber.HasProvider<IProvidesPlaneFinding>())
    74.                     m_Subscriber.StartDetectingPlanes();
    75.  
    76.                 if (m_Subscriber.HasProvider<IProvidesMarkerTracking>())
    77.                     m_Subscriber.StartTrackingMarkers();
    78.             }
    79.         }
    80.  
    81.         public void TriggerSessionReset()
    82.         {
    83.             if (m_Subscriber.HasProvider<IProvidesSessionControl>())
    84.                 m_Subscriber.ResetSession();
    85.         }
    86.     }
    87. }
    88.  
    This is from an app that we use to test MARS, and is hooked up to a UI canvas with buttons and a text object to indicate status. You may notice that the `Subscriber` sub-class is actually what implements `IUsesSessionControl`, etc. This allows us to include this script in our scene without adding a requirement for planes, point clouds, and image markers, but still to control those systems if they are active.

    Feel free to keep the questions coming. If this example doesn't make sense, I can provide a simpler one that just covers the basics.

    Cheers!
     
    glitchbeam, EarMaster and dtaddis like this.
  5. EarMaster

    EarMaster

    Joined:
    Mar 7, 2013
    Posts:
    38
    Thanks for your help.
     
    mtschoen likes this.
  6. secret_portal_mike

    secret_portal_mike

    Joined:
    Jul 11, 2018
    Posts:
    5
    This was a super helpful thread! I have a similar issue where I want to "start fresh" at various times in my app's lifetime. One thing I'm noticing: say I start doing some AR stuff in one room, and then pause the session while I do some stuff in the menus of the apps. In the meantime, I could walk into another room. When I unpause the session again, it seems very eager to latch onto planes from the previous room, and the new room's planes come in very slowly or not at all. I'd love to "wipe clean" the set of detected planes, so the other room is essentially "forgotten". Is there a way to trigger this? I didn't see a relevant function on the IUsesPlaneFinding interface. Am I missing something?
     
  7. EarMaster

    EarMaster

    Joined:
    Mar 7, 2013
    Posts:
    38
    The only thing that in the end worked reliably was to add a ARFoundation Session to the scene, call Reset() on this session, then reload the whole scene and wait for a few seconds as the tracking was very unreliable otherwise.

    I got in direct contact with the MARS team, but unfortunately they weren't able to provide another solution to me. They assured me though to look into it.
     
  8. mtschoen

    mtschoen

    Unity Technologies

    Joined:
    Aug 16, 2016
    Posts:
    139
    Hi there, @secret_portal_mike!

    The `TriggerSessionReset` method in the script I pasted should do what you are describing, which resets the whole AR session including scanned surfaces. @EarMaster was this not working for you?

    Edit: sorry--I pressed enter trying to fill in the @mention and it hit reply instead! :)
     
  9. IF_test

    IF_test

    Joined:
    Feb 27, 2017
    Posts:
    10
    Hello, i aslo wants to reset the facetracking session. will m_Subscriber.ResetSession(); reset facetracking session too?

    also tried to call "TriggerSessionReset()" on button click is not resetting session. its not entering in to if condition block.
     
    Last edited: Jan 29, 2021
  10. mtschoen

    mtschoen

    Unity Technologies

    Joined:
    Aug 16, 2016
    Posts:
    139
    Hi there! `TriggerSessionReset` should be working, but if `HasProvider` is returning false, then there must be an issue where the face tracking configuration doesn't have a session control provider. We will investigate this issue and get back to you with more information.

    Something you could try is to "promote" session control in this class which would tell the system you require a session control provider. To do this, simply move the `IUsesSessionControl` interface from the `Subscriber` nested class up to the `SessionUI` class definition and move the provider property out of the subscriber class. Then you should be able to just call `this.ResetSession()` in `TriggerSessionReset`. You would end up with something more similar. to the snippet I posted here https://forum.unity.com/threads/turn-off-mars-camera.1044880/#post-6773267
     
unityunity