I’m developping an application for Hololens 2, with Unity 2023.1.16f1, AR Foundation 5.1.0, OpenXR Plugin 1.8.2 and Mixed Reality OpenXR Plugin 1.9.0.
I use multiples ARAnchor to anchor a 3D model in real environment. I also use an XRAnchorStore and an XRAnchorTransferBatch to persist and share anchors across multiple Hololens.
For some reason I ignore, sometimes the XROrigin starts to spam NullReferenceException (1 at each frame, the Hololens starts to lag):
It comes from this in XROrigin.OnBeforeRender:
if (TrackablesParent.hasChanged)
{
TrackablesParentTransformChanged?.Invoke(new ARTrackablesParentTransformChangedEventArgs(this, TrackablesParent));
TrackablesParent.hasChanged = false;
}
Because there is an excption in the event triggered, the TrackablesParent.hasChanged flag is never set to false…
I think one of my anchor has been destroyed but not removed from the trackables list in the ARTrackableManager.OnTrackablesParentTransformChanged function (the ARTrackableManager is the base class of the ARAnchorManager I use).
void OnTrackablesParentTransformChanged(ARTrackablesParentTransformChangedEventArgs eventArgs)
{
foreach (var trackable in trackables)
{
var transform = trackable.transform; // I think here trackable is null
if (transform.parent != eventArgs.TrackablesParent)
{
var desiredPose = eventArgs.TrackablesParent.TransformPose(trackable.sessionRelativePose);
transform.SetPositionAndRotation(desiredPose.position, desiredPose.rotation);
}
}
}
Does anyone know this issue or from where it comes?
We don’t have access to the protected m_Trackables dictionnary, destroyed anchors should have been removed automatically (most of the time, it works). I’m still investigating, but I don’t have a constant bug reproduction.
The spaming starts when World Locking Tools moves the XROrigin to compensate for Hololens drift: the trackables parent transform has changed and the exception loop starts.
When I disable World Locking Tools, I don’t have anymore null trackables in the ARAnchorManager trackables list.
Side note: I have another issue with WLT. When active, the ARAnchorManager event OnAnchorsChanged(ARAnchorsChangedEventArgs eventArgs) doesn’t contains the added anchors…
Thanks for the question. I’m really late and not really on point, but could you please share the sample of loading the anchors back from the transfer batch? I’m trying to migrate from the old WorldAnchorStore/TransferBatch APIs, and the MixedReality OpenXR Pluging seems to have the equivalent classes, but they return these TrackableIDs instead and I can’t seem to find how to turn those into the actual anchors on Unity game objects. I understand the principles since HoloLens 1 and Unity 2019 but somehow lost in all the new Unity’s XR architectural layers.
To load the anchors back from an XRAnchorTransferBatch, I do the following:
/// <summary> Anchors comming from a shared anchoring. </summary>
protected Dictionary<TrackableId, string> _incomingAnchors = new Dictionary<TrackableId, string>();
public override async UniTask Import(Stream stream)
{
XRAnchorTransferBatch batch = await XRAnchorTransferBatch.ImportAsync(stream);
if (batch != null)
{
foreach (string name in batch.AnchorNames)
{
TrackableId trackableId = batch.LoadAnchor(name);
if (trackableId != TrackableId.invalidId)
{
_incomingAnchors.Add(trackableId, name);
}
}
}
else
{
Debug.LogWarning("Batch is null, failed to import anchoring");
}
}
Then, your ARAnchorManager event OnAnchorsChanged will be triggered (a frame later) with the new created anchors. You can get a reference to them, in the same script:
private ARAnchorManager anchorManager;
private void Awake()
{
anchorManager = GetComponent<ARAnchorManager>();
anchorManager.OnAnchorsChanged += OnAnchorsChanged;
}
private void OnDestroy()
{
anchorManager.OnAnchorsChanged -= OnAnchorsChanged;
}
private void OnAnchorsChanged(ARAnchorsChangedEventArgs eventArgs)
{
foreach (ARAnchor anchor in eventArgs.added)
{
if (_incomingAnchors.TryGetValue(anchor.trackableId, out string name))
{
_incomingAnchors.Remove(anchor.trackableId);
// do here what you need to do with the reference to the new ARAnchor component
}
}
}