visionOS 2.0中平面锚转世界锚后模型位置偏移问题求助
将平面锚点转换为世界锚点后模型位置异常(visionOS 2.0)
我尝试把Reality Composer Pro里的.usda模型放到墙面锚点上,为了保存锚点位置,想把初始的AnchorEntity从.plane类型转成.world类型。文档里说AnchorEntity有reanchor()方法,但这个方法在visionOS 2.0里已经被弃用了:
@available(visionOS, deprecated, message: "reanchor(:preservingWorldTransform:) is not supported on xrOS")
测试时平面锚点能正确放置,但获取它的变换并初始化世界锚后,模型位置不符合预期,看起来在原点。
代码实现
创建平面锚点
let planeAnchor = AnchorEntity(.plane(.vertical, classification: .wall, minimumBounds: [1.0, 1.0]), trackingMode: .once)
初始化世界锚点
let anchor = getPlaneAnchor() NSLog("planeAnchor \(anchor.transform)") guard anchor.transform.translation != .zero else { return NSLog("Anchor transformation is zero.") } let worldAnchor = WorldAnchor(originFromAnchorTransform: anchor.transformMatrix(relativeTo: nil)) NSLog("worldAnchor \(worldAnchor.originFromAnchorTransform)")
跟踪会话处理
case .added: let model = ModelEntity(mesh: .generateSphere(radius: 0.1)) model.transform = Transform(matrix: worldAnchor.originFromAnchorTransform) worldAnchors[worldAnchor.id] = worldAnchor anchoredEntities[worldAnchor.id] = model contentRoot.addChild(model)
调试信息
// planeAnchor Transform(scale: SIMD3<Float>(0.99999994, 0.99999994, 0.99999994), rotation: simd_quatf(real: 1.0, imag: SIMD3<Float>(1.5511668e-08, 0.0, 0.0)), translation: SIMD3<Float>(-1.8068967, 6.8393486e-09, 0.21333294)) // worldAnchor simd_float4x4([[0.99999994, 0.0, 0.0, 0.0], [0.0, 0.99999994, 3.1023333e-08, 0.0], [0.0, -3.1023333e-08, 0.99999994, 0.0], [-1.8068967, 6.8393486e-09, 0.21333294, 1.0]])
问题原因与解决方案
核心问题
直接将平面锚点的世界变换矩阵赋值给模型是错误的,WorldAnchor需要通过WorldAnchorEntity关联到RealityKit场景的跟踪体系,手动设置变换会脱离ARKit的坐标系上下文,导致模型位置偏移到原点。
修正代码
1. 从平面锚点创建世界锚点实体
let anchor = getPlaneAnchor() guard anchor.transform.translation != .zero else { return NSLog("Anchor transformation is zero.") } // 创建WorldAnchor并关联到WorldAnchorEntity let worldAnchor = WorldAnchor(originFromAnchorTransform: anchor.transformMatrix(relativeTo: nil)) let worldAnchorEntity = WorldAnchorEntity(worldAnchor: worldAnchor) // 将锚点实体添加到场景根节点 contentRoot.addChild(worldAnchorEntity) // 将模型作为锚点实体的子节点,自动继承锚点位置 let model = ModelEntity(mesh: .generateSphere(radius: 0.1)) worldAnchorEntity.addChild(model) // 保存引用 worldAnchors[worldAnchor.id] = worldAnchor anchoredEntities[worldAnchor.id] = model
2. 跟踪会话中处理WorldAnchor更新
case .added(let worldAnchor): // 基于新添加的WorldAnchor创建实体 let worldAnchorEntity = WorldAnchorEntity(worldAnchor: worldAnchor) contentRoot.addChild(worldAnchorEntity) // 添加模型到锚点实体 let model = ModelEntity(mesh: .generateSphere(radius: 0.1)) worldAnchorEntity.addChild(model) worldAnchors[worldAnchor.id] = worldAnchor anchoredEntities[worldAnchor.id] = model
关键说明
WorldAnchor是纯数据对象,无法直接在场景中定位内容,必须通过WorldAnchorEntity作为载体,它会自动处理ARKit世界坐标系与RealityKit场景的映射。- 将模型作为
WorldAnchorEntity的子节点,模型会自动继承锚点的位置和姿态,无需手动设置变换矩阵。 - 确保在平面锚点完成跟踪(
trackingState为.normal)后再获取其变换创建世界锚点,避免拿到未初始化的变换数据。
内容的提问来源于stack exchange,提问作者user28088635
相关产品推荐
相关产品推荐

