swift - 调度队列以在 ARKit 中为 SCNNode 设置动画

标签 swift grand-central-dispatch scenekit arkit

我在尝试定期为 ARSession 上的节点设置动画时遇到问题。我每 5 秒从 Internet 获取数据,然后使用该数据更新此节点(缩小或放大)。 我的代码看起来像这样:

Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { timer in
    fetchDataFromServer() {
        let fetchedData = $0
        DispatchQueue.main.async {
            node1.update(fetchedData)
            node2.update(fetchedData)
            node3.update(fetchedData)
        }
        if stopCondition { timer.invalidate() }
    }
}

问题是在调用更新时我看到了一个小故障,在这个小故障中相机似乎卡住了几分之一秒并且我在控制台中看到以下消息:[Technique] World tracking performance is being affected受资源限制 [1] 更新正确发生,但如果每 5 秒我得到这些“短暂卡住”,用户体验真的很笨拙

我也试过创建并发队列: 让 animationQueue = DispatchQueue(标签:“animationQueue”,属性:DispatchQueue.Attributes.concurrent) 并调用 animationQueue.async 而不是主队列,但问题仍然存在。 如果有任何建议,我将不胜感激。

编辑:update 方法中的每个子节点如下所示

private func growingGeometryAnimation(newHeight height: Float) -> CAAnimation{
    // Change height
    let grow = CABasicAnimation(keyPath: "geometry.height")
    grow.toValue = height
    grow.fromValue = prevValue

    // .... and the position
    let move = CABasicAnimation(keyPath: "position.y")
    let newPosition = getNewPosition(height: height)
    move.toValue = newPosition.y + (yOffset ?? 0)

    let growGroup = CAAnimationGroup()
    growGroup.animations = [grow, move]
    growGroup.duration = 0.5
    growGroup.beginTime = CACurrentMediaTime()
    growGroup.timingFunction = CAMediaTimingFunction(
        name: kCAMediaTimingFunctionEaseInEaseOut)
    growGroup.fillMode = kCAFillModeForwards
    growGroup.isRemovedOnCompletion = false

    growGroup.delegate = self

    return growGroup
}
self.addAnimation(growingGeometryAnimation(newHeight: self.value), forKey: "bar_grow_animation")

最佳答案

要对场景进行任何更新,请使用 SCNTransaction,它确保所有更改都在适当的线程上进行。

Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { timer in
    fetchDataFromServer() {
        let fetchedData = $0

        SCNTransaction.begin()
        node1.update(fetchedData)
        node2.update(fetchedData)
        node3.update(fetchedData)
        SCNTransaction.commit()

        if stopCondition { timer.invalidate() }
    }
}

关于swift - 调度队列以在 ARKit 中为 SCNNode 设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47522995/

相关文章:

ios - Swift - 将 subview 从 xib 加载到 UIScrollView 后,滚动不起作用并且 subview 超出范围

ios - 我无法让这个 CA 动画正常工作

swift - 如何确保 CLLocationManager 在主线程上延迟实例化?

objective-c - 有没有办法让相机缩放但不旋转?

swift - 如何在 ARKit 中使用环境贴图?

iOS:如何在推送到 viewController 后继续显示 subview

ios - 使用 AVMutableCompositionTrack 合并 AVMutableComposition 中的视频和图像,而不是 AVVideoCompositionCoreAnimationTool?

ios - 从 iOS 应用程序在服务器上实现动态搜索的最佳方式是什么?

objective-c - 如何通过dispatch concurrent queue (GCD)实现可重入锁机制?

ios - ARKIT - 它可以跟踪多少个跟踪图像?