Azure Spatial Anchor Android端await CreateAnchorAsync卡住问题求助
Azure Spatial Anchor Android平台锚点保存卡顿问题
问题背景
原本在HoloLens上运行正常的Azure Spatial Anchor(ASA)锚点保存功能,适配Android平台时出现异常:调用await _spatialAnchorManager.CreateAnchorAsync(cloudSpatialAnchor);时代码卡住,无任何报错信息。
此前为确保环境数据采集充分,曾使用while循环等待SessionStatus.RecommendedForCreateProgress达标,但该逻辑在Android上会直接导致应用冻结,因此已注释。HoloLens端无此问题,暂不认为是锚点保存失败的直接原因。
核心代码
private async Task CreateAnchor(Vector3 position) { //Create Anchor GameObject. We will use ASA to save the position and the rotation of this GameObject. 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; //Add and configure ASA components CloudNativeAnchor cloudNativeAnchor = anchorGameObject.AddComponent<CloudNativeAnchor>(); if (cloudNativeAnchor.CloudAnchor == null) { await cloudNativeAnchor.NativeToCloud(); } CloudSpatialAnchor cloudAnchor = cloudNativeAnchor.CloudAnchor; // Then we create a new local cloud anchor CloudSpatialAnchor cloudSpatialAnchor = new CloudSpatialAnchor(); // Now we set the local cloud anchor's position to the native XR anchor's position cloudSpatialAnchor.LocalAnchor = await anchorGameObject.FindNativeAnchor().GetPointer(); // Check to see if we got the local XR anchor pointer if (cloudSpatialAnchor.LocalAnchor == IntPtr.Zero) { return; } //Collect Environment Data /*while (!_spatialAnchorManager.IsReadyForCreate) // debug 20.12.2022 { float createProgress = _spatialAnchorManager.SessionStatus.RecommendedForCreateProgress; UnityEngine.Debug.Log($"ASA - Move your device to capture more environment data: {createProgress:0%}"); }*/ try { // Now that the cloud spatial anchor has been prepared, we can try the actual save here. await _spatialAnchorManager.CreateAnchorAsync(cloudSpatialAnchor); bool saveSucceeded = cloudSpatialAnchor != null; if (!saveSucceeded) { return; } _foundOrCreatedAnchorGameObjects.Add(anchorGameObject); _createdAnchorIDs.Add(cloudSpatialAnchor.Identifier); anchorGameObject.GetComponent<MeshRenderer>().material.color = Color.green; } catch (Exception exception) { UnityEngine.Debug.LogException(exception); } }
已尝试操作
- 取消注释
while循环等待环境数据采集进度,应用直接冻结
求助问题
如何解决代码卡在await _spatialAnchorManager.CreateAnchorAsync(cloudSpatialAnchor);处且无报错的问题?
解决方案建议
1. 修复环境数据采集的阻塞问题
原来的while循环会阻塞主线程导致Android应用冻结,改用协程+异步回调的方式等待采集完成:
private IEnumerator WaitForCreateReady(Vector3 position) { while (!_spatialAnchorManager.IsReadyForCreate) { float progress = _spatialAnchorManager.SessionStatus.RecommendedForCreateProgress; UnityEngine.Debug.Log($"ASA 环境数据采集进度: {progress:P0}"); yield return new WaitForSeconds(0.5f); // 避免高频刷新占用资源 } // 采集完成后执行锚点创建 _ = ExecuteCreateAnchor(position); } // 重构锚点创建核心逻辑 private async Task ExecuteCreateAnchor(Vector3 position) { // 此处放置原CreateAnchor方法中除环境等待外的所有逻辑 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 = anchorGameObject.AddComponent<CloudNativeAnchor>(); if (cloudNativeAnchor.CloudAnchor == null) { await cloudNativeAnchor.NativeToCloud(); } CloudSpatialAnchor cloudSpatialAnchor = new CloudSpatialAnchor(); var nativeAnchor = anchorGameObject.FindNativeAnchor(); if (nativeAnchor == null) { UnityEngine.Debug.LogError("找不到Native Anchor"); return; } cloudSpatialAnchor.LocalAnchor = await nativeAnchor.GetPointer(); if (cloudSpatialAnchor.LocalAnchor == IntPtr.Zero) { UnityEngine.Debug.LogError("LocalAnchor指针无效"); return; } try { await _spatialAnchorManager.CreateAnchorAsync(cloudSpatialAnchor); bool saveSucceeded = cloudSpatialAnchor != null; if (!saveSucceeded) { return; } _foundOrCreatedAnchorGameObjects.Add(anchorGameObject); _createdAnchorIDs.Add(cloudSpatialAnchor.Identifier); anchorGameObject.GetComponent<MeshRenderer>().material.color = Color.green; } catch (Exception exception) { UnityEngine.Debug.LogException(exception); } }
调用时替换原逻辑:
// 不再直接调用CreateAnchor,改为启动协程等待采集完成 StartCoroutine(WaitForCreateReady(targetPosition));
2. 强化LocalAnchor有效性校验
Android平台上FindNativeAnchor().GetPointer()可能返回隐性无效指针,添加多层校验:
var nativeAnchor = anchorGameObject.FindNativeAnchor(); if (nativeAnchor == null) { UnityEngine.Debug.LogError("Native Anchor对象为空"); return; } cloudSpatialAnchor.LocalAnchor = await nativeAnchor.GetPointer(); if (cloudSpatialAnchor.LocalAnchor == IntPtr.Zero) { UnityEngine.Debug.LogError("LocalAnchor指针无效"); return; }
3. 检查Android权限与网络配置
- 确保
AndroidManifest.xml中添加必要权限:<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - 排查网络连接:Android平台可能存在代理、防火墙拦截ASA云端请求,可通过抓包或Unity日志查看网络请求状态。
4. 验证SDK版本兼容性
检查Azure Spatial Anchor SDK版本是否与Unity XR插件(如AR Foundation/ARCore)版本匹配,Android平台对版本兼容性要求更严格,建议使用ASA官方文档推荐的配套版本。
内容的提问来源于stack exchange,提问作者ChocooPanda
相关产品推荐
相关产品推荐

