应用Transform后如何获取Entity真实的朝向/旋转角度值?
RealityKit 获取 Entity 当前旋转角度实现方法
核心原因
entity.orientation返回的是simd_quatf四元数类型,不会直接返回弧度/角度格式的欧拉角数值,你需要手动完成四元数到欧拉角的转换,转换时需要匹配RealityKit默认的旋转顺序:pitch(绕X轴俯仰)→ yaw(绕Y轴偏航)→ roll(绕Z轴翻滚),避免计算结果偏差。
可直接复用的转换代码
给simd_quatf写扩展,直接从四元数取出弧度制的三个欧拉角:
import simd extension simd_quatf { /// 返回弧度制欧拉角,顺序为(pitch: 俯仰X轴, yaw: 偏航Y轴, roll: 翻滚Z轴) var eulerAngles: (pitch: Float, yaw: Float, roll: Float) { let x = imag.x, y = imag.y, z = imag.z, w = real // 计算X轴pitch let sinPitch = 2 * (w * x + y * z) let cosPitch = 1 - 2 * (x * x + y * y) let pitch = atan2(sinPitch, cosPitch) // 计算Y轴yaw,处理万向锁边界 let sinYaw = 2 * (w * y - z * x) let yaw: Float if abs(sinYaw) >= 1 { yaw = copysign(.pi / 2, sinYaw) } else { yaw = asin(sinYaw) } // 计算Z轴roll let sinRoll = 2 * (w * z + x * y) let cosRoll = 1 - 2 * (y * y + z * z) let roll = atan2(sinRoll, cosRoll) return (pitch, yaw, roll) } }
调用方式
替换你原来的打印逻辑即可拿到符合预期的角度值:
entity.setOrientation(transform.rotation, relativeTo: nil) // 获取当前旋转值 let currentEuler = entity.orientation.eulerAngles print("pitch 弧度值:\(currentEuler.pitch)") // 输出约1.5708,对应.pi/2 print("pitch 角度值:\(currentEuler.pitch * 180 / .pi)") // 输出约90.0
旋转范围限制实现提示
做交互旋转限制时,按以下逻辑处理即可:
- 每次识别到用户旋转手势,先计算手势带来的pitch增量
- 用当前pitch值加上增量得到目标pitch值
- 用
clamp方法把目标pitch限制在-.pi/2~.pi/2(即-90°~90°)区间 - 用限制后的pitch值生成新的旋转四元数,赋值给实体即可
注意:如果设置旋转时用的是
relativeTo: nil(世界坐标系),取orientation得到的也是世界坐标系下的旋转值,参考系一致不会出现计算偏差;如果是相对父实体旋转,要对应使用entity.orientation(relativeTo: 父实体)取值。
内容的提问来源于stack exchange,提问作者ZbadhabitZ
相关产品推荐
相关产品推荐

