ios - SCNAction 回调仅在设备上调用一次并在模拟器上正确调用

标签 ios swift scenekit

编辑

我比较了在 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 何时完成执行?

最佳答案

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

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

您对 runAction(_:completionHandler:) 的使用,定义在 SCNActionable 协议(protocol)上,看起来是正确的。

编辑:我尝试在 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)
        }
    }
}
}

关于ios - SCNAction 回调仅在设备上调用一次并在模拟器上正确调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35444765/

相关文章:

swiftui - 如何使 SceneView 的背景透明?

javascript - Google Maps API 无法在 iPad 上加载

ios - 释放使用 initFromFile 方法创建的对象时崩溃

ios - 链接器命令失败,退出代码为 1 xcode 6.4

当 Swift 文件包含在框架中时,不会编译前缀项目文件头中的 Objective-C 宏

iphone - 从搜索结果 UITableView 添加 segue

ios - 使用 Metal 顶点和片段着色器将 MTLTexture 传递给 SCNProgram

ios - 在 Scenekit ios 的自定义场景类中我需要什么方法?

iphone - TTPhotoViewController:停用图库自动缩放

ios - 从 cellForRowAt 更新时,UITableViewCell 中的事件约束不会更新