This pairs with today’s study on whether mediated attendance delivers a sense of being present. That paper separates spatial presence from participatory agency. Anchors are the most concrete tool we have for the first half: they are how a virtual thing acquires a stable location in a real room, so that it is somewhere rather than merely in front of you.
The problem anchors solve
In a headset, your app’s coordinate system is established when tracking starts. It is not the room’s coordinate system; it is this session’s. Put a sculpture on the coffee table, quit, come back tomorrow, and your sculpture is at the same coordinates — which are now somewhere else entirely, because the origin moved.
A spatial anchor is a pose the system stores against its own understanding of the physical space. You ask the runtime to remember this spot in this room, it gives you an identifier, and on a later session you hand the identifier back and get the spot returned. The headset does the work of recognising the room.
That is the whole concept. The implementation details are where people get stuck.
Before you write any code: two settings
1. Enable Anchor Support. You can do this through the AndroidManifest or, more conveniently, in OVRManager on the OVRCameraRig. If you skip it, anchor calls fail silently enough to waste an afternoon.
2. You need passthrough in your scene. Spatial anchors do not work without it. This catches people who assume anchors are a general persistence feature and try to use them in a fully virtual scene — the anchoring system is part of the mixed-reality stack and expects to be able to see the room.
Sharing is a separate setting, and you only need it if you intend to share anchors between users or devices. Do not turn it on by reflex; it changes what the app declares it does with spatial data.
The lifecycle
Meta’s own documentation describes the Unity component as encapsulating a spatial anchor’s entire lifecycle — creation, destruction and persistence — and you add it with a script call rather than dragging it onto an object in the editor.
The flow you are implementing:
- Create. Add the anchor component to a GameObject at the pose you want remembered. The anchor is now live for this session.
- Wait for it to localise. An anchor is not immediately valid. Check that it has been created and localised before you trust its pose or try to save it. This is the single most common source of “it works sometimes” bugs.
- Save. Persist it, and keep the UUID the system returns. The anchor lives in the headset’s storage; your job is storing the identifier.
- Load. On a later session, query by the saved UUID. The runtime attempts to localise it in the current space. It can fail — different room, rearranged furniture, insufficient tracking — so handle the unbound case.
- Erase. Remove it from persistent storage and from the scene. Users accumulate anchors invisibly; give them a way to clear them.
Store the UUIDs yourself. PlayerPrefs is fine to learn with and fine for a single-user demo. Anything shipping wants something you can enumerate, label and clear, because “the user has 40 saved anchors and no idea which is which” is a real end state.
Start from the sample, not from scratch
Meta’s Starter Samples include a SpatialAnchor scene requiring Unity 2022.3 or later. It demonstrates creating anchors, saving them, loading them back, and erasing them from persistent storage — including the erase path, which tutorials usually skip and which you will need.
Open it, run it on device, then read it. The API has changed more than once and a working sample on your Unity version is worth more than any written guide, including this one.
Persistence is not sharing
Worth separating clearly, because the words get used loosely:
- Persistence — the same user, the same device, a later session. One anchor, one UUID, stored locally.
- Sharing / colocation — several users in the same physical room seeing content in the same place. This needs the sharing capability, a way to distribute UUIDs between users, and for the devices to agree on the space. Meta’s Shared Spatial Anchors and Colocation Discovery cover this.
Build persistence first. Colocation adds networking, session management and a second class of failure, and debugging both at once is miserable.
Testing it properly
The test that matters is boring and nobody does it: place an anchor, quit the app, take the headset off, leave the room, come back later, relaunch. Anchors that work when you quit and immediately relaunch frequently fail after a real absence, because that is when the headset genuinely has to re-recognise the space rather than coasting on warm tracking.
Also test deliberate failure: move the furniture, or run the app in a different room, and confirm your code does something sensible when localisation does not succeed. An unbound anchor rendering your content at the origin, inside the user’s head, is the classic outcome.
Unreal
If you are in Unreal rather than Unity, Meta’s shared anchors sample covers persisting anchor UUIDs across sessions. The concepts transfer exactly; only the API surface differs.
Sources
- Meta Quest Spatial Anchors | Create, Save, Erase & Load spatial anchors — Roberto Coviello on YouTube
- Use Spatial Anchors to Persist Content — Meta Horizon Documentation
- Starter Sample: Spatial Anchor — Meta Horizon Documentation
- Spatial anchors in Unity tutorial — Brown University VR Wiki
- Unreal shared anchors sample — Meta Developers