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.

Arfoundation How To Properly Remove Planes And Ref Points

Discussion in 'AR' started by AndyLangberg, Apr 15, 2019.

Thread Status:
Not open for further replies.
  1. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    I have a setup where the user scans for surfaces, clicks on one, and attaches a ref point to that surface. This worked fine until I wanted to implement a reset button that destroys all surfaces and the ref point:



    Code (CSharp):
    1. _arReferencePointManager.TryRemoveReferencePoint(_arRefTrackable);
    2. Destroy(_arRefPoint);
    3. var planeList = new List<ARPlane>();
    4. _arPlaneManager.GetAllPlanes(planeList);
    5. foreach (var arPlane in planeList)
    6.     Destroy(arPlane);
    7.  

    This results in a spam of errors every frame as it's trying to create a new plane at the same position as the one I just removed:


    ArgumentException: An item with the same key has already been added. Key: D04E208B120CD64E-8FF5A5DD81B1B4B2
    at System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.XR.ARFoundation.ARPlaneManager.AddPlane (UnityEngine.Experimental.XR.BoundedPlane boundedPlane) [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.XR.ARFoundation.ARPlaneManager.OnPlaneUpdated (UnityEngine.Experimental.XR.PlaneUpdatedEventArgs eventArgs) [0x00000] in <00000000000000000000000000000000>:0
    at System.Action`1[T].Invoke (T obj) [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.XR.ARFoundation.ARSubsystemManager.OnPlaneUpdated (UnityEngine.Experimental.XR.PlaneUpdatedEventArgs eventArgs) [0x00000] in <00000000000000000000000000000000>:0
    at System.Action`1[T].Invoke (T obj) [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.Experimental.XR.XRPlaneSubsystem.InvokePlaneUpdatedEvent (UnityEngine.Experimental.XR.BoundedPlane plane) [0x00000] in <00000000000000000000000000000000>:0

    (Filename: currently not available on il2cpp Line: -1)


    So it looks like Destroy(ARPlane) isn't a legal way to do it, but looking through the documentation I can't find any other way to remove one. ARSession.Reset() works somewhat, but it resets the camera and everything else, so it's a bit overkill and makes for a bad user experience.
     
    Last edited: Apr 15, 2019
  2. tdmowrer

    tdmowrer

    Unity Technologies

    Joined:
    Apr 21, 2017
    Posts:
    605
    You should not manually Destroy components that are created by one of the managers.

    You can remove a reference point with TryRemoveReferencePoint.

    ARPlanes should not be removed while the plane manager is enabled. The exception you get comes from the fact that it is trying to update the planes almost every frame. Even if we added a check to handle the case where the plane has been destroyed outside its control, it would simply re-add the plane the next time it gets an updated by ARCore or ARKit.

    Having the plane manager enabled tells ARFoundation "I want you to add ARPlanes to my scene and update their GameObjects whenever ARCore/ARKit says they have changed." What are you trying to achieve by Destroy'ing them?
     
  3. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    The main problem some of our test users have reported is that the planes quickly gets quite messy. After moving around between tables there's planes on each one, sometimes several planes overlapping but not joining together for whatever reason, there's planes on the floor beneath the work surfaces, suddenly the laptop gets its own plane, etc etc. So to fix this issue I thought to have the user select a plane in the beginning, add a reference point with an infinitely (more or less) large unity-plane that the user can actually work with, and then hide the meshes of the existing AR planes and new ones. This isn't a problem to do, so far so good.

    Issue comes when the user wants to select a new plane. While the user has moved around there would be a huge new amount of planes being made in the background that he doesn't see, and the second he turns them back on (by re-enabling the meshes), there's going to be a huge mess again. So instead I wanted to simply remove all planes and start scanning anew. But I see no way to do this with the current available functions. Even removing the manager and adding a new one doesn't work, as it's never able to "retrack" a previously tracked surface. The only thing that does work is restarting the whole session, which also restarts the camera. The latter is the implementation I'm currently using, but it does not make for a very smooth user experience. Removing planes would be a whole lot easier, not to mention open up new possibilities for different use cases.
     
    Propagant likes this.
  4. tdmowrer

    tdmowrer

    Unity Technologies

    Joined:
    Apr 21, 2017
    Posts:
    605
    If you want to hide/disable certain planes, you can deactivate those GameObjects, e.g.,
    Code (csharp):
    1. foreach(var plane in planes)
    2. {
    3.     plane.gameObject.SetActive(false);
    4. }
    Would that help?
     
  5. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    No, because when the user then "resets" the planes, and we reactivate them, there will suddenly (from the user's point of view) be a ton of planes all over the place that clutters up the place and makes it difficult to choose a new surface. I really need to be able to delete planes for this solution to be viable.
     
  6. Blarp

    Blarp

    Joined:
    May 13, 2014
    Posts:
    267
    remove plane manager.

    use this in your raycast hits at your screen center cursor

    https://docs.unity3d.com/ScriptReference/Experimental.XR.TrackableType.PlaneEstimated.html

    I believe that is closer inline with what you are looking for. You only need to know the plane in which someone is placing a 3d object upon correct? You only need to know the plane position when someone wants to put something down.

    Then slap a reference point so it doesn't drift
     
    Last edited: Apr 30, 2019
    yty likes this.
  7. Blarp

    Blarp

    Joined:
    May 13, 2014
    Posts:
    267
    ~
     
    Last edited: Apr 30, 2019
  8. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    This is a possible solution. However I think it is good user experience to let the user know which planes they'll be able to select/place the reference point on, as such there needs to be something visible on the screen for the user to click on, which PlaneEstimated doesn't give.
     
    Blarp likes this.
  9. fotalik

    fotalik

    Joined:
    Sep 23, 2017
    Posts:
    24
    @AndyLangberg if you are call
    ARSubsystemManager.planeSubsystem.Stop()
    then ARFoundation will no longer create new Planes in background, while playing user, for example, after player placed an object.
    And when a player presses the Reset button, you need to re-activate this Subsystem again and all Planes return to their places correctly. I had no problems with it :)
     
  10. Arvizio_JD

    Arvizio_JD

    Joined:
    Jan 21, 2019
    Posts:
    1
    We are in the same boat, ARPlaneManager.RemovePlane() only seems to remove the plane till the next update planes event and does not appear to remove the plane from the XRPlaneSubsystem. I tried removing the plane and destroying the game object in trackables with no success. I also tried destroying the ARPlaneManager and creating a new instance of it but as soon as a new plane combines with an existing plane in the XRPlaneSubsystem it disappears, I am assuming because the plane with the original id has been removed from the Trackables object in the scene and when the new plane combines with it the new plane gets destroyed.

    it would be great if there was a way of clearing out the planes in the XRPlaneSubsystem or if ARPlaneManager.RemovePlane() worked as expected. I do not understand the purpose of ARPlaneManager.RemovePlane() if the plane comes back right away and is not removed from the subsystem.

    We most likely use ARSession.Reset() but I also think this is over kill. Resting a single subsystem would be nice as well.

    Justin.
     
    artfabrik likes this.
  11. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    This doesn't quite do what we want. People who use our app are expected to move to different workplaces, and we don't want "old planes" on other surfaces to still be alive when they do. After a while there's going to be an absolutely massive amount of surfaces that is going to clog up the app and make it messy for the user. We want to be able to remove them without restarting the whole AR session.
     
  12. Tarrag

    Tarrag

    Joined:
    Nov 7, 2016
    Posts:
    215
  13. Blarp

    Blarp

    Joined:
    May 13, 2014
    Posts:
    267
    Use the plane detection as a reference and instantiate your final plane(s) as a new plane gameobject after the fact. That way you have more control over them on cleanup. I'm not sure how you save the generated planes, but instantiate planes in its place and save those instead.

    All those planes have to localize/anchor against something to be in the right spot, such as an image target or point cloud map.
     
    Sprarage likes this.
  14. misher

    misher

    Joined:
    Apr 22, 2016
    Posts:
    19
    Disable plane manager (+ disable all ARPlane children) . Call Reset() on your AR Session. Wait a couple of frames. Enable plane manager.
     
  15. NatAle11

    NatAle11

    Joined:
    Dec 17, 2019
    Posts:
    1
    @AndyLangberg

    ¿Lograste resolverlo ?, estoy tratando de hacer lo mismo que tú y no he tenido éxito
     
  16. augmentaio

    augmentaio

    Joined:
    Jun 14, 2016
    Posts:
    8
    How would you destroy only one specific plane? You cannot call Rest() hera as it would destroy all detected planes. I want the PlaneManager to create a new plane at the same location some time later. Therefor hiding the old plane wouldn't do because the updates would be applied to the hidden GameObject. Any suggestions?
     
  17. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    984
    As others suggested above, you're not allowed to destroy trackables. To disable plane generation and planes update, you can set
    ARPlaneManager.detectionMode
    to
    PlaneDetectionMode.None
    . And then change it back to
    PlaneDetectionMode.Horizontal 
    when you wish to continue.


    var planeManager = FindObjectOfType<ARPlaneManager>();
    planeManager.detectionMode = PlaneDetectionMode.None;
     
  18. augmentaio

    augmentaio

    Joined:
    Jun 14, 2016
    Posts:
    8
    but that simply pauses my plane detection, so when I resume the old plane will be back, right? So it doesn't solve my problem: I want to delete a specific plane which ARPlaneManager detected erroneously
     
  19. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    984
    Just disable the erroneously detected plane with gameObject.SetActive(false);
     
  20. AndriesG

    AndriesG

    Joined:
    Nov 22, 2014
    Posts:
    1
    I want to do the same thing. I can't understand why it is so hard as it seems like some very basic functionality...
     
    viknesh2020 and timmy2get like this.
  21. ibompuis

    ibompuis

    Joined:
    Sep 13, 2012
    Posts:
    99
    H KirillKuzyki, but how you know the erroneously plane ? how do you select it when you have multiple plane ? thx
     
  22. Tarrag

    Tarrag

    Joined:
    Nov 7, 2016
    Posts:
    215
    efge and ibompuis like this.
  23. JakeZubr

    JakeZubr

    Joined:
    Nov 11, 2021
    Posts:
    1
    I found an easy solution to this. You just have to reference the AR Session and call session.Reset(). Worked for my needs.
     
    dev_unity203 and adityaspt like this.
Thread Status:
Not open for further replies.