ARFoundation - Error with Trackable being updated this frame

,

Hi,

Sometimes I’m getting the following error in Unity with ARFoundation:

InvalidOperationException: Trackable 1E355E4000000000-FF08060000000000 being updated this frame has at least one other action associated with it.
UnityEngine.XR.ARSubsystems.ValidationUtility1[T].AddToSetAndThrowIfDuplicate (UnityEngine.XR.ARSubsystems.TrackableId trackableId, System.Boolean shouldBeInDictionary, System.String action) (at Library/PackageCache/com.unity.xr.arsubsystems@4.1.1/Runtime/TrackingSubsystem/ValidationUtility.cs:65) UnityEngine.XR.ARSubsystems.ValidationUtility1[T].ValidateAndThrow (UnityEngine.XR.ARSubsystems.TrackableChanges1[T] changes) (at Library/PackageCache/com.unity.xr.arsubsystems@4.1.1/Runtime/TrackingSubsystem/ValidationUtility.cs:32) UnityEngine.XR.ARSubsystems.ValidationUtility1[T].ValidateAndDisposeIfThrown (UnityEngine.XR.ARSubsystems.TrackableChanges1[T] changes) (at Library/PackageCache/com.unity.xr.arsubsystems@4.1.1/Runtime/TrackingSubsystem/ValidationUtility.cs:55) UnityEngine.XR.ARSubsystems.XRPlaneSubsystem.GetChanges (Unity.Collections.Allocator allocator) (at Library/PackageCache/com.unity.xr.arsubsystems@4.1.1/Runtime/PlaneTracking/XRPlaneSubsystem.cs:81) UnityEngine.XR.ARFoundation.ARTrackableManager4[TSubsystem,TSubsystemDescriptor,TSessionRelativeData,TTrackable].Update () (at Library/PackageCache/com.unity.xr.arfoundation@4.1.1/Runtime/AR/ARTrackableManager.cs:187)

I really don’t know what could be causing this. Any idea?

Looks like it happens when creating my own trackable under the “Trackables” gameobject that is managed by the ARTrackableManager.

Bump!

Hi @danUnity_1 , can you please file a bug with reproducible project so the team can properly track and take a look? Thanks!

I got the same error when disabling the planeManager and deactivated all trackables like the following:

planeManager.enabled = false;
planeManager.SetTrackablesActive(false);

and later enabled the planeManager again:

planeManager.enabled = true;

Did you find the solution already?

I haven’t had the time to fill a bug report because I’m on a time crunch. @Premtey could you do that if you were able to reproduce the issue? That would be a life saver!

Yes, I can and yes, I will :smile:

Thank you!! :slight_smile:

@danUnity_1
I presume this is in a debug-build? (Validate&Throw only runs in a debug-build.

This Exception is thrown if the TrackableId is already in the IdSet and was added again (duplicate entry, s_IdSet is a HashSet):


You say you are ‘creating my own trackable under the “Trackables” gameobject’. Are you duplicating an existing one?

@Premtey I’m guessing in your case the PlaneManager is re-adding already existing planes due to being disabled & re-enabled?

Correct, the PlaneManager is re-adding already existing planes when disabling and then re-enabling again. Do I have to change anything to avoid this exception?

As I’ve said above: This code only runs on Debug-Builds. It will not appear in a non-debug-build.
You can check XRPlaneSubsystem.GetChanges() in the com.unity.xr.arsubsystems-package for the Compiler-directives. It serves as an additional check for duplicates coming from the underlying provider. (ARKit does not seem to override this method. Not sure about ARCore atm).

Unity’s ARFoundation-team will need to take a look at what to do with ‘duplicate entries’ and disabling/re-enabling managers. They’d also have to discuss this with the engineers behind ARCore/ARKit, and clarify the desired behaviour. (<- i.e. link this thread in the bug-report. It will be useful :wink: )

What’s annoying is that this will also dispose the NativeArrays in the ‘changes’-object. This means that the behaviour will differ between debug- and non-debug-builds. A work-around for this is to make a ‘local’ copy of the ARSubsystems-package and remove the call altogether.

Actually… Scratch (some of) what I said above (and in the previous post).
After looking at ValidationUtility.ValidateAndThrow again, I noticed that it actually clears the s_IdSet right at the start.

What this means:
The ValidationUtility does NOT check for duplicates within the system. It checks for duplicates within the TrackableChanges-object itself.

When this can throw:

  • If a single Array (e.g. added) contains two instances of the same TrackableId → Highly unlikely, as a provider would be expected to keep only the ‘most recent’ version of the ‘change’ itself (keying by the trackableId internally as well)
  • If a TrackableId exists across multiple arrays. → Actually quite likely

First of all: @Premtey : What I think is happening for you is that after disabling the manager, it still runs ‘internally’ for another frame. It thus exists in 2 arrays, e.g.:

  • Updated (on Disable) + Added (on re-enable)
  • Removed (on Disable) + Added (on re-enable)
    A way around this would be to ‘clear’ the changes before re-enabling. Thus:
    Disable → Next Frame → Call GetChanges() (dump contents) → Next Frame → Re-Enable

as for @danUnity_1 : Not sure what’s happening in your case. I’m guessing the Id also exists across multiple arrays, but I’m not sure how adding your own Trackable would change this (unless you’re somehow creating multiple trackables with the same TrackableId?)

As I’m currently writing an XRPlugin myself, I’m pinging @mfuad to see if he can give some perspective into the ‘intended’ behaviour, and if a provider should/shouldn’t allow a trackable to have multiple ‘changes’ in a single call to GetChanges. 2 things seem unclear to me here:

1. What is the intended behaviour for a provider when ‘shutting down’?
- Clear all changes?
- Delete all existing trackables?
- Use new Guids for the objects after re-enabling?
2. What should a provider do if it is enabled but GetChanges is not being called every frame?
- Keep only latest change?
- Keep latest change of each type?

2 Likes

Thanks for your time and answer. It helped me understand why it happens!