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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 14:17:38