iOS RealityKit 修改Entity的translation后出现Y值异常增长问题
问题原因&修复方案
核心问题1:坐标空间不匹配
Entity.transform属性返回的是实体相对于父节点(也就是你挂载Toy的AnchorEntity)的本地变换,但你调用move(to:relativeTo:)时传入relativeTo: nil,代表目标变换是基于世界空间的坐标。如果AnchorEntity的世界坐标y值不为0,或者运行中ARKit重定位导致Anchor位置漂移,你基于本地变换计算、硬设y为0的新坐标传入世界空间后就会出现y轴偏移。
核心问题2:动画触发逻辑不可靠
你用DispatchQueue.main.asyncAfter来延迟触发完成回调,无法保证前一次移动动画已经完全执行完毕,若下一次walk调用时前次动画还在运行,读取到的currentTransform就是动画过程中的中间值,也会导致y轴数值异常。
核心问题3:骨骼动画根运动干扰
如果你的Toy是带骨骼行走动画的模型,动画本身如果开启了根运动,可能自带y方向的上下位移,和你代码控制的位移叠加后就会出现y轴不受控增长的情况。
具体修复步骤
- 修正坐标空间匹配
把move方法的relativeTo参数改为实体的父节点,保证目标变换是基于父节点的本地空间,你硬设的y=0就会正常生效:
// 把原来的 nil 改成 robot.parent robot.move(to: newTransform, relativeTo: robot.parent, duration: travelTime)
- 替换为系统提供的动画完成回调
不要自己用定时器判断动画结束,直接用move方法自带的完成回调,保证前次动画完全结束后再触发下一次移动:
func walk(completion: @escaping () -> Void) { guard let robot = robot else { return } let currentTransform = robot.transform guard let path = randomPath(from: currentTransform) else { return } let (newTranslation , travelTime) = path let newTransform = Transform(scale: currentTransform.scale, rotation: currentTransform.rotation, translation: newTranslation) // 用move的自带回调判断动画完成 robot.move(to: newTransform, relativeTo: robot.parent, duration: travelTime) { _ in DispatchQueue.main.asyncAfter(deadline: .now() + 1) { completion() } } }
- 锁定动画根运动的y轴(如果是骨骼动画模型)
加载模型后关闭动画根运动的y轴影响,避免动画本身修改实体的y坐标:
// 模型加载完成后添加这段代码 robot.availableAnimations.forEach { anim in let repeatAnim = anim.repeat() // 禁用动画带来的y轴根位移 repeatAnim.configuration.isRootMotionEnabled = false robot.playAnimation(repeatAnim) }
快速排查技巧
你可以在每次调用walk时打印两个值,快速定位偏移来源:
print("本地y:\(robot.transform.translation.y)")查看相对于Anchor的本地y坐标是否正常print("世界y:\(robot.position(relativeTo: nil).y)")查看世界空间下的y坐标是否和预期一致
内容的提问来源于stack exchange,提问作者Kuba Gawecki
相关产品推荐
相关产品推荐

