2016-12-02 83 views
5

我创建了一个可供玩家移动的SceneKit 3D迷宫世界。一些像跳跃这样的动作涉及在上下移动照相机的同时在几秒钟的时间内改变视角。在此期间,我想忽略用户的点击和挥动,这通常会导致其他类型的动作,如转动和向前移动。检查SCNNode SCNAction是否已完成

我可以创建相匹配的跳跃时间,并设置一个布尔值,但我希望检查摄像机的SCNNode的simplier方式的计时器。

有一个简单的方法,如果摄像机的SCNNode不再运行SCNAction的跳转,所以我可以在其他轻触和滑动操作的前面加上这样的逻辑?

或者也许有一个SCNAction可以设置布尔,我可以在我的跳转序列的开始和结束?

这里是我的跳码:

 let jumpUp: SCNAction = SCNAction.move(to: SCNVector3Make(Float(Int(-yPos)), Float(Int(xPos)), jumpHeight), duration: jumpTime) 
     let jumpAppex: SCNAction = SCNAction.wait(duration: jumpWaitTime) 
     let fallDown: SCNAction = SCNAction.move(to: SCNVector3Make(Float(Int(-yPos)), Float(Int(xPos)), cameraHeight), duration: jumpTime) 

     var lookDown: SCNAction = SCNAction.rotateTo(x: 0, y: 0, z: CGFloat(π), duration: jumpTurnTime) 
     let noLook: SCNAction = SCNAction.wait(duration: jumpTime*2.0) 
     var lookBack: SCNAction = SCNAction.rotateTo(x: 0, y: 0, z: 0, duration: jumpTurnTime) 

     switch playerDirection.direction 
     { 
      case .south: 
       lookDown = SCNAction.rotateTo(x: 0, y: 0, z: CGFloat(southZ), duration: jumpTurnTime) 
       lookBack = SCNAction.rotateTo(x: CGFloat(π/2), y: 0, z: CGFloat(southZ), duration: jumpTurnTime) 
      case .north: 
       lookDown = SCNAction.rotateTo(x: 0, y: 0, z: CGFloat(northZ), duration: jumpTurnTime) 
       lookBack = SCNAction.rotateTo(x: CGFloat(π/2), y: 0, z: CGFloat(northZ), duration: jumpTurnTime) 
      case .east: 
       lookDown = SCNAction.rotateTo(x: 0, y: 0, z: CGFloat(eastZ), duration: jumpTurnTime) 
       lookBack = SCNAction.rotateTo(x: CGFloat(π/2), y: 0, z: CGFloat(eastZ), duration: jumpTurnTime) 
      case .west: 
       lookDown = SCNAction.rotateTo(x: 0, y: 0, z: CGFloat(westZ), duration: jumpTurnTime) 
       lookBack = SCNAction.rotateTo(x: CGFloat(π/2), y: 0, z: CGFloat(westZ), duration: jumpTurnTime) 
     } 

     let sequenceJump = SCNAction.sequence([jumpUp, jumpAppex, fallDown]) 
     let sequenceLook = SCNAction.sequence([lookDown, noLook, lookBack]) 

     mazeScene.mazeCamera.runAction(sequenceJump) 
     mazeScene.mazeCamera.runAction(sequenceLook) 

感谢

格雷格

+1

有一个''runBlock' SCNAction',你可以只添加到您的顺序和定块内的布尔。还有一个'runAction:completionHandler'方法在动作完成时运行一个块。 –

+0

原因苹果无法记录自己的最佳功能,因为这是你即将看到的。 IMNSHO,这是最好和最强大的行动,几乎完全没有记录,并且从未提升它的内容,可以并且代表着承诺和潜力:https://developer.apple.com/reference/scenekit/ scnaction/1523692-customaction – Confused

回答

3

我最终使用一个.customAction:

我添加了一个类变量isJumping

然后在我加入功能码的前面:

isJumping = true 

,并添加了SCNAction:

let jumpDone: SCNAction = SCNAction.customAction(duration: 0, action: {_,_ in self.isJumping = false}) 

再变序列:

let sequenceLook = SCNAction.sequence([lookDown, noLook, lookBack, jumpDone]) 

然后我就如果isJumping,看看跳跃运动已完成做一个。

3

操作是相当奇怪的事情,我想。

这个想法很大程度上受到了cocos2D的启发(基本上是1:1映射和'盗窃'),在那里它们被用来避免直接与游戏循环,状态和时间(某种)交互。动作为处理时间和创建和调用活动提供了一种模块化和抽象,并对其结论进行了非常原始的处理。

读这里的时候,你可以看到是多么相似SpriteKit和SceneKit的行动是原来的想法:http://python.cocos2d.org/doc/programming_guide/actions.html

由于其创作的不同和不断变化的自然结果,有人忘了给他们自己的认识状态,尽管它们影响节点状态的某些方面。这将使得Action对象具有“运行”状态几乎完美。但据我所知,他们没有。

相反,你可以检查节点是否有规定动作,如果是的话,它的推断行动正在运行。

尽管跨越时间的持续时间做一些大多数操作,你也无法查询他们,他们已经在多大程度上通过自己的时间做到了,也没有什么价值,他们已经刚刚解雇,或将下一个发送。但是有些行为可以做到这一点,特别是为了应对所有行为都没有的事实,意味着如果你想要这个,你需要使用一个特殊的Action来提供这个。

对于本来应该是天生的设施而言,这种回归自我的行为最令人讨厌的部分并不是从熟悉时间轴和关键帧的人的角度来思考。

整体上,并在总结:您无法查询动作的状态,也不是它的进步,或者只是做或明年将使用的值。这绝对是荒谬的。

我不知道如何在操作的各种变阵忽视...他们的时间管理和模块化的活性创造者。将状态和进度报告包含在他们之中似乎是合乎逻辑的......好吧,我不知道......只是奇怪他们没有。

因此,要回答你的问题:

  1. 您可以使用完成处理,这是当一个动作完成一些代码调用为设定值或调用其他功能或收拾东西,或无论你想要什么..

  2. 序列动作,在一个SCNAction.sequence ...这是一种方法让一个动作顺序运行,并在内部使用一些动作,当你想要运行代码块,调用设置你需要什么,什么时候需要,按照动作的顺序。所有这一切都可以避免,如果行动当前对时间和财产的价值具有透明度......但是......

  3. 你也可以使用少数特殊行动,由于对它们所做的更改而进行编辑。我只熟悉SKEaseKit中的浮动设置功能,但您可能可以在SceneKit和SpriteKit中执行此操作(如果您比我更好的编码器)。 SKEaseKit隐藏了一些非常有用的值更改操作。

我使用它,例如,像这样的,其中,这种混乱改变的0到1的值跨越的持续时间(时间),在这种情况下直线,并且每个帧(希望)更新的.xScale在其本growAction被运行的节点:

let growAction = SKEase.createFloatTween(
       start: 0, 
       ender: 1, 
       timer: time, 
       easer: SKEase.getEaseFunction(.curveTypeLinear, 
      easeType: .easeTypeOut), 
      setterBlock: {(node, i) in 
      node.xScale = i} 
      ) 
1

有一个runAction(_:completionHandler:),在那里你可以处理完成。请参阅documentation

所以,你可以通过完成街区,这里检查的必要条件:

mazeScene.mazeCamera.runAction(sequenceJump) { print("Sequence jump is completed") }

+0

我看到[James P](https://stackoverflow.com/users/488611/james-p)在该问题下发表评论。我相信它应该是一个单独的答案。至少,它可以帮助我一段时间。 –

相关问题