Azure Spatial Anchor跨设备共享锚点失败技术求助
问题诊断与解决方案
1. ShareAnchorAsync 方法不存在的问题
Azure Spatial Anchors(ASA)的 CloudSpatialAnchor 类从未提供过 ShareAnchorAsync 或 ShareAsync 方法,你混淆了其他SDK的API逻辑。ASA中锚点的共享无需额外"共享"操作,只要锚点成功保存到云端,其他设备使用锚点的系统标识符即可检索,前提是两台设备使用同一ASA资源的配置凭据,且处于同一区域。
2. 锚点创建代码的冗余与潜在问题
你的代码同时混用了 CloudNativeAnchor 和手动构建 CloudSpatialAnchor 的逻辑,会导致冗余甚至锚点保存异常。简化并修正创建逻辑如下:
private async Task CreateAnchor(Vector3 position) { if (!InputDevices.GetDeviceAtXRNode(XRNode.Head).TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 headPosition)) { headPosition = Vector3.zero; } Quaternion orientationTowardsHead = Quaternion.LookRotation(position - headPosition, Vector3.up); GameObject anchorGameObject = GameObject.Instantiate(_CubePrefab); anchorGameObject.GetComponent<MeshRenderer>().material.color = Color.white; anchorGameObject.transform.position = position; anchorGameObject.transform.rotation = orientationTowardsHead; anchorGameObject.transform.localScale = Vector3.one * 0.1f; // 仅使用CloudNativeAnchor处理锚点转换与云端保存 CloudNativeAnchor cloudNativeAnchor = anchorGameObject.AddComponent<CloudNativeAnchor>(); // 等待ASA会话准备好创建锚点 while (!_spatialAnchorManager.IsReadyForCreate) { await Task.Delay(330); float createProgress = _spatialAnchorManager.SessionStatus.RecommendedForCreateProgress; _TxtDebug.text = $"Déplacer le téléphone jusqu'à que le cube devienne vert: {createProgress:0%}%"; } _TxtDebug.text = ""; try { // 将本地锚点转换为云端锚点并保存 await cloudNativeAnchor.NativeToCloud(); CloudSpatialAnchor cloudSpatialAnchor = cloudNativeAnchor.CloudAnchor; if (cloudSpatialAnchor == null) { UnityEngine.Debug.Log("ASA - Failed to convert native anchor to cloud anchor"); return; } // 添加自定义属性(可选,用于后续批量查询) cloudSpatialAnchor.AppProperties["customTag"] = "myCustomLabel"; // 保存锚点到云端 await _spatialAnchorManager.CreateAnchorAsync(cloudSpatialAnchor); _foundOrCreatedAnchorGameObjects.Add(anchorGameObject); _createdAnchorIDs.Add(cloudSpatialAnchor.Identifier); // 输出锚点系统ID,需将此ID传递给其他设备用于检索 UnityEngine.Debug.Log("ASA - Anchor saved successfully, ID: " + cloudSpatialAnchor.Identifier); anchorGameObject.GetComponent<MeshRenderer>().material.color = Color.green; } catch (Exception exception) { UnityEngine.Debug.Log("ASA - Failed to save anchor: " + exception.ToString()); UnityEngine.Debug.LogException(exception); } }
3. 锚点检索的正确方式
你之前的检索逻辑错误在于:AnchorLocateCriteria.Identifiers 对应ASA系统生成的锚点ID(即 cloudSpatialAnchor.Identifier),而非存储在 AppProperties 中的自定义标签。
方式一:使用系统标识符直接检索
- 将创建设备生成的
cloudSpatialAnchor.Identifier通过二维码、蓝牙或后端服务传递给其他设备。 - 其他设备使用该ID检索:
// receivedAnchorId为从其他设备获取的系统锚点ID AnchorLocateCriteria criteria = new AnchorLocateCriteria(); criteria.Identifiers = new string[] { receivedAnchorId }; _spatialAnchorManager.Session.CreateWatcher(criteria); // 监听锚点找到事件 _spatialAnchorManager.AnchorLocated += (sender, args) => { switch (args.Status) { case LocateAnchorStatus.Located: // 将云端锚点转换为本地GameObject GameObject anchorGameObject = GameObject.Instantiate(_CubePrefab); CloudNativeAnchor cloudNativeAnchor = anchorGameObject.AddComponent<CloudNativeAnchor>(); cloudNativeAnchor.CloudToNative(args.Anchor); anchorGameObject.GetComponent<MeshRenderer>().material.color = Color.blue; _foundOrCreatedAnchorGameObjects.Add(anchorGameObject); break; case LocateAnchorStatus.AlreadyTracked: case LocateAnchorStatus.NotLocatedAnchorDoesNotExist: case LocateAnchorStatus.NotLocated: UnityEngine.Debug.Log($"ASA - Anchor locate status: {args.Status}"); break; } };
方式二:使用自定义属性批量查询锚点
若需通过自定义标签批量检索锚点,需使用ASA的查询API:
// 查询所有带有customTag=myCustomLabel的锚点 SqlQuery anchorQuery = new SqlQuery($"customTag = 'myCustomLabel'"); AsyncPageable<CloudSpatialAnchor> queryResult = _spatialAnchorManager.Session.QueryAnchorsAsync(anchorQuery); await foreach (CloudSpatialAnchor anchor in queryResult) { // 转换为本地GameObject GameObject anchorGameObject = GameObject.Instantiate(_CubePrefab); CloudNativeAnchor cloudNativeAnchor = anchorGameObject.AddComponent<CloudNativeAnchor>(); cloudNativeAnchor.CloudToNative(anchor); anchorGameObject.GetComponent<MeshRenderer>().material.color = Color.blue; _foundOrCreatedAnchorGameObjects.Add(anchorGameObject); }
4. 额外检查项
- 确保两台设备使用完全相同的ASA资源配置(Account ID、Account Key、Account Domain),且资源区域一致。
- 设备需处于联网状态,能正常访问ASA云端服务。
- 锚点创建时必须等待
IsReadyForCreate为true,确保采集了足够的空间数据,否则锚点可能无法被其他设备识别。
内容的提问来源于stack exchange,提问作者ChocooPanda
相关产品推荐
相关产品推荐

