Showing results for 
Search instead for 
Did you mean: 

How to propperly Align Players/OVRCameraRigs to Shared Spatial Anchors?

Honored Guest

I have a net code project where i try to use spatial anchors to achieve co-location type of game. 

  • I am using Meta Core SDK and the provided OVR Camera Rig (OVR Manager, OVR Camera Rig)...
  • I am using netcode 
  • I am trying to align the Player in the camera rig to the spatial anchor.

I managed to synchronize the anchor location, both players see the anchor in the same real life physical location. What I'm struggling with is aligning the joining players to the anchor so their characters overlap with their real life bodies.

The flow of logic so far.

1. I spawn the anchor at 0,0,0 for the host

2. Save it, and Share it with players in the lobby

3. Re-Share with joining players. 

4. bind unbound anchor for client players, and wait for it to be created and localized

(to this point everything is fine, both players see the anchor, but are not align to it yet.)

:exclamation_mark:5. Align the client player to the anchor (this is where everything aligns wrongly)

The alignment code is basically the same as the one found in sample packages, i take in a OVRSpatialAnchor, then set the "OVRCameraRig" position to 0,0, then setting the "OVRCameraRig" position to the "anchorTransform.InverseTransformPoint("

The problem is that after running the alignment code the "zero zero" is put far away outside the playable space about exactly 5 meters wrong on x and z. And if i try to manually correct for this using "camerarigwhatevr += new vector(-5,0,-5)" it just becomes more wrong.

Bellow you find my alignment code. I know its something about this code, cause the anchor itself is always physically in the same spot for all players, its only the aligning that is wrong. I constantly compare to both the sample projects, and i cannot find any differences that should affect this.

Based on these Samples

Unity-Discover/Packages/com.meta.xr.sdk.colocation/Anchors/AlignmentAnchorManager.cs at main · oculu...

Unity-SharedSpatialAnchors/Assets/SharedSpatialAnchors/Scripts/AlignPlayer.cs at main · oculus-sampl...

My alignment code (with debugging stuff) (i manually trigger the align with a button bind so i can see what happens more easily): 



using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// A Script to bind local player positions to the networked player.
public class LocalPlayer : MonoBehaviour
    public static LocalPlayer Instance;

    [Header("Colocation Alignment")]
    [SerializeField] Transform _cameraRigTransform;
    [SerializeField] Transform _playerHandsTransform;
    private void Awake()
        Instance = this;
    private void Update()
        if (OVRInput.GetDown(OVRInput.RawButton.A)) AlignPlayerToColocation();

    private Coroutine _alignmentCoroutine;
    public static void AlignPlayerToColocation()
        if (CoLocationAnchorManager.Singleton.LoadedAnchor == null)
            Logger.Log("No colocation anchor");
    public void AlignPlayerToAnchor(OVRSpatialAnchor anchor)
        Debug.Log("AlignmentAnchorManager: Called AlignPlayerToAnchor");
        if (_alignmentCoroutine != null)
            _alignmentCoroutine = null;

        _alignmentCoroutine = StartCoroutine(AlignmentCoroutine(anchor, 2));
    OVRSpatialAnchor _currentAlignement;
    private IEnumerator AlignmentCoroutine(OVRSpatialAnchor anchor, int alignmentCount)
        Debug.Log("PlayerAlignment: called AlignmentCoroutine");
        while (!anchor.Created)
            yield return null;
        while (!anchor.Localized)
            yield return null;

        Logger.Log("BEFORE ALIGN [" + alignmentCount + "]: Player Transform : " + _cameraRigTransform.position);
        Logger.Log("BEFORE ALIGN [" + alignmentCount + "]: Anchor Transform : " + anchor.transform.position);
        while (alignmentCount > 0)
            if (_currentAlignement != null)
                // Reset the position to zero
                _cameraRigTransform.position =;
                _cameraRigTransform.eulerAngles =;
                Logger.Log("ALIGN [" + alignmentCount + "]: Player Transform : " + _cameraRigTransform.position);
                Logger.Log("ALIGN [" + alignmentCount + "]: Anchor Transform : " + anchor.transform.position);
                // wait one frame for anchor to move
                yield return null;

            var anchorTransform = anchor.transform;
            if (_cameraRigTransform != null)
                // set the position to be the inverse of the Ancor Transform Position (Relative to its new position)
                // this kinda gets the anchors releative position to the world origin.
                _cameraRigTransform.position = anchorTransform.InverseTransformPoint(;
                Logger.Log("ALIGN Inverse [" + alignmentCount + "]: Player Transform : " + _cameraRigTransform.position);
                Logger.Log("ALIGN Inverse [" + alignmentCount + "]: Anchor Transform : " + anchor.transform.position);
                _cameraRigTransform.eulerAngles = new Vector3(0, -anchorTransform.eulerAngles.y, 0);
                Logger.Log("ALIGN: CameraRigTransform is invalid");

            if (_playerHandsTransform != null)
                _playerHandsTransform.localPosition = -_cameraRigTransform.position;
                _playerHandsTransform.localEulerAngles = -_cameraRigTransform.eulerAngles;
            _currentAlignement = anchor;
            yield return new WaitForEndOfFrame();
        Logger.Log("ALIGN FINAL [" + alignmentCount + "]: Player Transform : " + _cameraRigTransform.position);
        Logger.Log("ALIGN FINAL [" + alignmentCount + "]: Anchor Transform : " + anchor.transform.position);
        Debug.Log("PlayerAlignment: Finished Alignment!");
        Logger.Log("Alignment Finished?");
    public Action OnAfterAlignment;





I am trying to do the same. Such a bad thing that Meta does not answer or provide any package or tutorial regarding multiplayer co-located experiences.