如何让RealityKit模型绕任意点而非中心点旋转?
在visionOS中实现对象绕选中点旋转
要让RealityView中的对象绕触摸选中的点(比如立方体边角)旋转,核心是通过射线检测获取命中点,再调整对象的变换逻辑,步骤如下:
1. 捕获触摸命中的精确点
在拖拽手势的回调里,利用RealityView的射线检测能力,从触摸位置发射射线,命中目标对象时记录世界空间下的命中坐标。
2. 转换坐标获取本地偏移
将世界空间的命中点转换为目标对象本地空间的坐标,得到该点相对于对象中心点的偏移量,后续旋转时需要基于这个偏移来调整位置。
3. 组合平移与旋转实现绕点旋转
旋转时,先将对象平移,让选中点对齐到世界空间的原命中位置,执行旋转后再平移回对应位置,确保旋转轴心始终是用户选中的点。
代码示例
struct RotateAroundHitPointView: View { @State private var targetEntity: Entity? @State private var hitWorldPosition: SIMD3<Float> = .zero @State private var initialLocalOffset: SIMD3<Float> = .zero @State private var initialRotation: simd_quatf = .init(angle: 0, axis: .zero) var body: some View { RealityView { content in // 加载Reality Composer Pro创建的场景 guard let scene = try? await Entity(named: "YourScene", in: .main) else { return } content.add(scene) // 替换为你场景中目标对象的名称 targetEntity = scene.findEntity(named: "Cube") } .gesture( DragGesture() .onChanged { gestureValue in guard let entity = targetEntity else { return } // 射线检测获取命中点 let raycastResults = content.raycast( from: gestureValue.location, allowing: .entity, alignmentTarget: .any ) if let hit = raycastResults.first, hit.entity == entity { hitWorldPosition = hit.position // 将世界坐标转为对象本地坐标,记录偏移 initialLocalOffset = entity.convert(position: hitWorldPosition, from: nil) initialRotation = entity.transform.rotation } // 计算拖拽产生的旋转角度(这里以绕Y轴为例) let rotationAngle = Float(gestureValue.translation.width / 80) let rotationAxis = SIMD3<Float>(0, 1, 0) let updatedRotation = simd_quatf(angle: rotationAngle, axis: rotationAxis) * initialRotation // 计算对象新位置:让选中点保持在原世界位置 let newWorldPosition = hitWorldPosition - entity.convert(position: initialLocalOffset, from: entity) // 应用新的变换 entity.transform = Transform( scale: entity.transform.scale, rotation: updatedRotation, translation: newWorldPosition ) } ) } }
注意事项
- 射线检测参数
allowing设为.entity可确保只命中目标实体,避免误触场景中其他对象; - 若目标对象有父节点,坐标转换时要注意空间层级,确保
convert方法的from参数正确; - 如需支持多手指旋转,可替换为
RotationGesture,核心逻辑保持一致,仅角度计算改为手势的旋转量。
内容的提问来源于stack exchange,提问作者Mark Tamotsu Kinoshita
相关产品推荐
相关产品推荐

