【问题标题】:SCNAction callback called only once on device and properly on simulatorSCNAction 回调仅在设备上调用一次并在模拟器上正确调用
【发布时间】:2016-02-18 03:53:57
【问题描述】:

编辑

我比较了在 iPhone (6+, 9.3 (13E5200d)) 上运行的结果,这是我的默认设置和 iOS 模拟器 (6+ 9.3 (13E5200d))。模拟器按预期工作。为什么两者之间存在差异?

我有一个看似简单的设置,我想在触摸时执行一系列动画。为此,我雇用了SCNAction。在每个动画之后,我想重新评估某些事情,所以我有一个在完成处理程序中调用的step 函数,而不是一个长的SCNAction.sequence()。问题是完成处理程序不会在任意数量的步骤之后被调用。

在这种情况下,这是一步。

let path = [
  SCNAction.sequence([
    SCNAction.moveBy(SCNVector3(2.7, 0, 0), duration: 0.25),
    SCNAction.waitForDuration(1)
  ]),
  SCNAction.sequence([
    SCNAction.moveBy(SCNVector3(2.7, 0, 0), duration: 0.25),
    SCNAction.waitForDuration(1)
  ]),
  SCNAction.sequence([
    SCNAction.moveBy(SCNVector3(2.7, 0, 0), duration: 0.25),
    SCNAction.waitForDuration(1)
  ]),
]

let nodeGeometry = SCNBox(width: 2.7, height: 2.7, length: 2.7, chamferRadius: 0)
nodeGeometry.firstMaterial = SCNMaterial()
nodeGeometry.firstMaterial?.diffuse.contents = UIColor.redColor()
let node = SCNNode(geometry: nodeGeometry)
scene.rootNode.addChildNode(node)

func step (index: Int) {
  print(index, "enter")
  node.runAction(path[index]) {
    print(index, "callback")
    if ((index + 1) < path.count) {
      step(index + 1)
    }
  }
}

step(0)

此代码产生以下序列

0 enter
0 callback
1 enter

我没有收到第二个回调。为什么?我如何知道SCNAction 何时完成执行?

【问题讨论】:

    标签: ios swift scenekit


    【解决方案1】:

    我刚刚在 OS X 操场上尝试了您的代码,它运行良好。红色块向右移动并消失在屏幕外。

    0 enter
    0 callback
    1 enter
    1 callback
    2 enter
    2 callback
    

    您对runAction(_:completionHandler:) 的使用(在SCNActionable 协议上定义)看起来不错。

    编辑:我尝试在 Xcode 7.2.x 和 7.3.beta3 下使用运行 9.2 的 iPad 和 iPhone 硬件。下面的代码稍作修改以安抚 Clang 之神,就像您描述的那样工作。要运行,请从 Xcode SceneKit 游戏模板开始,将 GameViewController 定义替换为以下代码,然后不理会项目的其余部分。

    class GameViewController: UIViewController {
    
    let path = [
        SCNAction.sequence([
            SCNAction.moveBy(SCNVector3(2.7, 0, 0), duration: 0.25),
            SCNAction.waitForDuration(1)
            ]),
        SCNAction.sequence([
            SCNAction.moveBy(SCNVector3(2.7, 0, 0), duration: 0.25),
            SCNAction.waitForDuration(1)
            ]),
        SCNAction.sequence([
            SCNAction.moveBy(SCNVector3(2.7, 0, 0), duration: 0.25),
            SCNAction.waitForDuration(1)
            ]),
    ]
    var boxNode: SCNNode?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let scene = SCNScene()
        let sceneView = view as! SCNView
        sceneView.scene = scene
        sceneView.backgroundColor = UIColor.darkGrayColor()
    
        let nodeGeometry = SCNBox(width: 2.7, height: 2.7, length: 2.7, chamferRadius: 0)
        nodeGeometry.firstMaterial = SCNMaterial()
        nodeGeometry.firstMaterial?.diffuse.contents = UIColor.redColor()
        boxNode = SCNNode(geometry: nodeGeometry)
        scene.rootNode.addChildNode(boxNode!)
    
        let sphereNode = SCNNode(geometry: SCNSphere(radius: 1))
        sphereNode.position = SCNVector3Make(7, 0, 4)
        scene.rootNode.addChildNode(sphereNode)
    }
    
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        step(0)
    }
    
    func step (index: Int) {
        print(index, "enter")
        boxNode!.runAction(path[index]) {
            print(index, "callback")
            if ((index + 1) < self.path.count) {
                self.step(index + 1)
            }
        }
    }
    }
    

    【讨论】:

    • 谢谢,这会留下可能导致问题的场景的其他部分...
    • 问题中的代码已经在使用runAction(_:completionHandler:)——它只是带有尾随闭包语法,所以第二个参数标签被省略了。
    • 哎呀,你是对的!不过,我复制/粘贴到操场上,效果很好。令人费解的是 OP 只看到一个电话。
    • 我在 iPhone 上对此进行了测试,在模拟器上运行相同的代码后,我看到了预期的行为。这可能与 9.3 测试版有关吗? @HalMueller @rickster?
    • @HalMueller 感谢您的更新。鉴于这对您有用,我现在确定是我运行 9.3 的硬件应该受到指责。花了一些时间到达那里:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多