visionOS沉浸式空间坐标系及Point3D单位转换的技术疑问
visionOS沉浸式空间坐标转换问题解析
问题背景
我正在测试一款使用沉浸式空间的visionOS应用,其中展示了一个不在原点的Box实体,点击该实体会打印返回的Point3D值。我先后测试了四种SpatialTapGesture版本:默认坐标系、.global坐标系、.local坐标系以及.immersiveSpace坐标系,不同坐标系下点击得到的Point3D值存在差异。
测试代码
struct ImmersiveView: View { var body: some View { RealityView { content in let mesh = MeshResource.generateBox(width: 1, height: 0.5, depth: 0.25, splitFaces: true) var frontMaterial = UnlitMaterial() frontMaterial.color.tint = .green var topMaterial = UnlitMaterial() topMaterial.color.tint = .red let boxEntity = ModelEntity(mesh: mesh, materials: [frontMaterial, topMaterial]) boxEntity.components.set(InputTargetComponent(allowedInputTypes: .all)) boxEntity.components[CollisionComponent.self] = CollisionComponent(shapes: [ShapeResource.generateConvex(from: mesh)]) boxEntity.transform.translation = [0, 0, -3] content.add(boxEntity) } .gesture(tapGesture) } var tapGesture: some Gesture { SpatialTapGesture(coordinateSpace: .local) .targetedToAnyEntity() .onEnded { event in let point3D = event.location3D print(point3D) } } }
测试发现
测试在模拟器中执行,记录不同坐标系下的点击坐标后发现:
SpatialTapGesture()默认使用.local坐标系;.local/默认与.global坐标系的坐标值大致相同,但存在以下差异:- 正面z值
.local比.global大约600; - 背面z值
.local比.global大约330,这与Box实体z轴偏移3米相关; - 盒子宽度约1300,高度约650,对应1m×0.5m的创建参数;
- 盒子深度在
.local下约230,.global下约300。
- 正面z值
疑问与解答
1. location3D返回值的单位是什么?如何转换为米?
location3D返回的单位是点(points),visionOS中1米等于1333点(即1pt = 1/1333 m)。你可以通过将返回的坐标值除以1333来转换为米单位。
验证你的测试数据:盒子宽度1300点除以1333约等于0.975米,和设置的1米参数接近;高度650点除以1333约等于0.488米,也和0.5米的设置匹配,完全符合这个转换比例。
2. 为什么盒子深度在.local和.global坐标系下存在差异?
这并非单纯的精度问题,核心原因是两个坐标系的原点定义不同:
.local坐标系的原点是你点击的实体(Box)自身的局部原点,也就是实体创建时的中心位置;.global坐标系的原点是整个沉浸式空间的世界原点。
你的Box实体的transform.translation设置为[0, 0, -3],也就是在世界坐标系中沿z轴负方向偏移了3米。当你点击盒子的正面或背面时,.local坐标系下的z值是相对于盒子自身中心的偏移,而.global坐标系下的z值是相对于世界原点的绝对位置,两者的差值正好对应实体的世界位置偏移。
另外,模拟器中的碰撞检测或射线投射可能存在微小的精度误差,也会导致数值上的细微差异,但主要原因还是坐标系原点的不同。
内容的提问来源于stack exchange,提问作者Reinhard Männer
相关产品推荐
相关产品推荐

