This article shows how to export and import spatial anchors in Unity using OpenXR, enabling persistence and sharing between HoloLens 2 devices. This resulting data can then be used to transfer the data. This allows you to persist the data either locally on a single HoloLens or to share the anchors between multiple devices.
This uses XRAnchorTransferBatch for “offline” cross-device anchor persistence in Unity OpenXR without having to resort to Azure Spatial Anchors (which has been retired as a cloud service as of November 2024), when cloud/online services are not an option or as a free alternative.
Requirements
- HoloLens 2
- Unity 2020+
- OpenXR plugin
- ARFoundation
Setup
The OpenXR plugin and ARFoundation can be installed via the Mixed Reality Feature Tool.
Make sure you have the AR Anchor Manager component in the scene. I’ve got my scene setup as follows:

Then you need an ARFoundation ARAnchor attached on the object on the location that you want to save.
Exporting the anchor
This can be used to grab the data from the anchors. This data can be saved locally, offline or shared with your networking solution of choice.
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.MixedReality.OpenXR;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
public async Task<byte[]> ExportAnchorsAsync(
IEnumerable<ARAnchor> anchors)
{
var batch = new XRAnchorTransferBatch();
foreach (var anchor in anchors)
{
// You usually store a mapping between ARAnchor and a string id yourself
batch.AddAnchor(anchor.trackableId, anchor.name);
}
Stream stream = await XRAnchorTransferBatch.ExportAsync(batch);
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
return ms.ToArray();
}
Importing
This is how you should load the data onto the HoloLens.
using Microsoft.MixedReality.OpenXR;
using System.IO;
using System.Threading.Tasks;
public async Task<XRAnchorTransferBatch> ImportAnchorsAsync(byte[] data)
{
using var stream = new MemoryStream(data);
XRAnchorTransferBatch batch =
await XRAnchorTransferBatch.ImportAsync(stream);
return batch;
}
Loading Anchors into the scene
After import, you explicitly request each anchor to be recreated in the Unity/XR session. You can also replace existing anchors.
public void LoadImportedAnchors(XRAnchorTransferBatch batch, string anchorName)
{
batch.LoadAnchor(anchorName);
}
public void ReplaceAnchor(
XRAnchorTransferBatch batch,
string anchorName,
TrackableId existingAnchorId)
{
batch.LoadAndReplaceAnchor(anchorName, existingAnchorId);
}
Completed file
Github gist: https://gist.github.com/Lansenou/caf479981f5757e36d86c684635e2303
Multiplayer
If you want players to see the information based around the Persistent Spatial Anchor you will need to make sure that the shared content in the scene is all placed relative to the anchor.
For example:
- Anchor (Same world position, parent of all objects)
- Object with a position relative to the anchor
This will show all the objects at the same world position.
Conclusion
To summarize the steps to correctly serialize a HoloLens anchor.
- Collect known anchors (
AddAnchor) - Serialize them into an opaque stream (
ExportAsync)- You can save these anchors for later usage or instantly transfer it to different HoloLens devices.
- Rebuild the anchor mapping on another device (
ImportAsync) - Let Unity resolve them back into live and local anchors (
LoadAnchor)
The anchor data itself is intentionally opaque by Microsoft. You’re not supposed to inspect or modify the batch, the code is there to send the anchor data between devices or sessions.
Projects that use sharing of anchors
Troubleshooting
Let me know if this information helped you! If you couldn’t make it work. Please contact me!
License
If you found this code useful, I’d appreciate a mention or a link back to this blog.
MIT License
Copyright (c) 2026 Lansenou.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
