You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 中的自定义标签。

方式一:使用系统标识符直接检索
  1. 将创建设备生成的 cloudSpatialAnchor.Identifier 通过二维码、蓝牙或后端服务传递给其他设备。
  2. 其他设备使用该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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 14:32:21