2016-12-02 169 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)在該問題下發表評論。我相信它應該是一個單獨的答案。至少,它可以幫助我一段時間。 –

相關問題