Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Thursday, June 8, for a Q&A with Unity's Content Pipeline group here on the forum, and on the Unity Discord, and discuss topics around Content Build, Import Workflows, Asset Database, and Addressables!
    Dismiss Notice

Question Reset MARS

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

  1. EarMaster


    Mar 7, 2013
    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


    Unity Technologies

    Aug 16, 2016
    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


    Mar 7, 2013
    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


    Unity Technologies

    Aug 16, 2016
    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;
    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.         }
    21.         [Serializable]
    22.         class PauseEvent : UnityEvent<bool> { }
    24.         const string k_PauseText = "Pause";
    25.         const string k_ResumeText = "Resume";
    27. #pragma warning disable 649
    28.         [SerializeField]
    29.         TextMeshProUGUI m_Text;
    30. #pragma warning restore 649
    32.         readonly Subscriber m_Subscriber = new Subscriber();
    34.         IProvidesFunctionalityInjection IFunctionalitySubscriber<IProvidesFunctionalityInjection>.provider { get; set; }
    36.         void Start()
    37.         {
    38.             m_Text.text = MARSCore.instance.paused ? k_ResumeText : k_PauseText;
    39.             this.InjectFunctionalitySingle(m_Subscriber);
    40.         }
    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.             }
    56.             MARSCore.instance.paused = paused;
    57.             if (paused)
    58.             {
    59.                 if (m_Subscriber.HasProvider<IProvidesPointCloud>())
    60.                     m_Subscriber.StopDetectingPoints();
    62.                 if (m_Subscriber.HasProvider<IProvidesPlaneFinding>())
    63.                     m_Subscriber.StopDetectingPlanes();
    65.                 if (m_Subscriber.HasProvider<IProvidesMarkerTracking>())
    66.                     m_Subscriber.StopTrackingMarkers();
    67.             }
    68.             else
    69.             {
    70.                 if (m_Subscriber.HasProvider<IProvidesPointCloud>())
    71.                     m_Subscriber.StartDetectingPoints();
    73.                 if (m_Subscriber.HasProvider<IProvidesPlaneFinding>())
    74.                     m_Subscriber.StartDetectingPlanes();
    76.                 if (m_Subscriber.HasProvider<IProvidesMarkerTracking>())
    77.                     m_Subscriber.StartTrackingMarkers();
    78.             }
    79.         }
    81.         public void TriggerSessionReset()
    82.         {
    83.             if (m_Subscriber.HasProvider<IProvidesSessionControl>())
    84.                 m_Subscriber.ResetSession();
    85.         }
    86.     }
    87. }
    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.

    nullcoolxyz, EarMaster and dtaddis like this.
  5. EarMaster


    Mar 7, 2013
    Thanks for your help.
    mtschoen likes this.
  6. secret_portal_mike


    Jul 11, 2018
    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


    Mar 7, 2013
    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


    Unity Technologies

    Aug 16, 2016
    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


    Feb 27, 2017
    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


    Unity Technologies

    Aug 16, 2016
    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