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

Oculus Quest 3 APK构建后无法保存OVRSpatialAnchor(本地/云端)求助

问题:Oculus Quest 3构建APK后空间锚点保存失败(编辑器正常)

在Unity 2023 + Meta XR All-in-One SDK v62环境下,编辑器中可正常将空间锚点保存至本地及云端,但构建APK在Quest 3设备运行时,调用OVRSpatialAnchor.Save()/SaveAsync()均失败;使用批量SaveAsync(IEnumerable<OVRSpatialAnchor>, SaveOptions)时返回OVRSpatialAnchors.OperationResult = Failure。

附当前SpatialAnchorManager核心代码:

private void CreateAnchor()
{
    var createdAnchor = Instantiate(anchor, OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTouch), OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTouch));
    var spatialAnchor = createdAnchor.AddComponent<OVRSpatialAnchor>();
    StartCoroutine(InitSpatialAnchor(spatialAnchor));
}

private IEnumerator InitSpatialAnchor(OVRSpatialAnchor anchor)
{
    yield return WaitForInit(anchor);
    yield return SaveAsync(anchor);
    // OnAnchorCreateCompleted?.Invoke(anchor);
}

protected IEnumerator WaitForInit(OVRSpatialAnchor anchor)
{
    while (anchor && (!anchor.Created || !anchor.Localized))
        yield return null;

    if (anchor == null)
    {
        Debug.LogWarning($" Failed to create the spatial anchor.");
    }
    else
    {
        var a = anchor.GetComponent<Anchor>();
        a.Uuid.text = $"Uuid: {anchor.Uuid}";
    }
}

protected IEnumerator SaveAsync(OVRSpatialAnchor anchor)
{
    var task = anchor.SaveAsync();
    while (!task.IsCompleted)
        yield return null;

    try
    {
        if (!task.GetResult())
        {
            var ex = task.GetType();
            debugText.text = $" Failed to save the spatial anchor.";
            Debug.LogWarning($" Failed to save the spatial anchor.");
        }
        else
        {
            var a = anchor.GetComponent<Anchor>();
            a.Status.text = $"Saved!!";
            PlayerPrefs.SetString("lastCreatedAnchor", anchor.Uuid.ToString());
        }
    }
    catch (Exception ex)
    {
        debugText.text = $"Exception After Saving: {ex.InnerException?.Message ?? ex.Message}";
    }
}

排查与修复步骤

1. 检查设备权限配置

  • 确认Project Settings > XR Plug-in Management > Meta XR中已勾选Spatial Anchors选项;
  • 验证AndroidManifest.xml包含必要权限(Meta SDK通常自动添加,需手动确认):
    <uses-permission android:name="com.oculus.permission.SPATIAL_ANCHORS"/>
    <uses-permission android:name="android.permission.INTERNET"/> <!-- 云端保存必填 -->
    
  • 检查设备应用权限列表,确保已授予空间锚点相关权限。

2. 完善锚点初始化验证

设备端锚点保存需要空间完成校准,现有逻辑仅判断Created和Localized,需补充空间校准状态检查:

protected IEnumerator WaitForInit(OVRSpatialAnchor anchor)
{
    while (anchor && (!anchor.Created || !anchor.Localized || !OVRSpatialAnchor.IsSpaceCalibrated))
        yield return null;

    if (!OVRSpatialAnchor.IsSpaceCalibrated)
    {
        Debug.LogError("空间未完成校准,无法保存锚点");
        // 可提示用户缓慢移动设备完成空间映射
        yield break;
    }

    // 原初始化成功逻辑...
}

3. 调整SDK与Unity版本兼容性

  • 尝试降级Meta XR SDK至v61(v62部分版本存在设备端空间锚点保存bug);
  • 确认Unity 2023子版本(如2023.1.x)与Meta SDK v62的兼容性,参考Meta官方兼容矩阵。

4. 优化错误捕获逻辑

当前代码未获取具体失败原因,修改SaveAsync以获取详细错误信息:

protected IEnumerator SaveAsync(OVRSpatialAnchor anchor)
{
    var task = anchor.SaveAsync();
    while (!task.IsCompleted)
        yield return null;

    try
    {
        var success = task.GetResult();
        if (!success)
        {
            var error = OVRSpatialAnchor.GetLastError(anchor.Uuid);
            var errorMsg = $"锚点保存失败,错误码:{error}";
            debugText.text = errorMsg;
            Debug.LogWarning(errorMsg);
        }
        else
        {
            // 原成功逻辑...
        }
    }
    catch (Exception ex)
    {
        var errorMsg = $"保存异常:{ex.InnerException?.Message ?? ex.Message}";
        debugText.text = errorMsg;
        Debug.LogError(errorMsg);
    }
}

5. 云端保存额外检查

若保存至云端,需确认:

  • 设备已登录Meta账号,且APP已关联Meta开发者后台的应用ID;
  • Meta开发者后台已启用Spatial Anchors Cloud服务;
  • 批量保存时锚点数量不超过SDK限制(单次建议不超过10个)。

内容的提问来源于stack exchange,提问作者mark sameh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 04:32:15