从SCNScene和overlaySKScene获取触摸事件的swift / scenekit问题

时间:2017-03-23 15:58:33

标签: swift scenekit

下午好,我正在试图弄清楚如何从SCNNode&来自SCNScene的SKSpriteNode与SKScene重叠。

import UIKit
import SceneKit
class GameViewController: UIViewController {
var scnView:SCNView!
var scnScene:SCNScene!
var sprite: spritekitHUD!
var cameraNode: SCNNode!
var shape: SCNNode!


override func viewDidLoad() {
    super.viewDidLoad()
    setupScene()
     }

func setupScene() {
    scnView = self.view as! SCNView
    scnView.delegate = self
    scnView.allowsCameraControl = true
    scnScene = SCNScene(named: "art.scnassets/scene.scn")
    scnView.scene = scnScene
    sprite=spritekitHUD(size: self.view.bounds.size, game: self)
    scnView.overlaySKScene=sprite
    cameraNode = scnScene.rootNode.childNode(withName: "camera",
                                              recursively: true)!
    shape=scnScene.rootNode.childNode(withName: "shape", recursively: true)
    shape.name="ThreeDShape"
    }

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
 let touch = touches.first!
 let location = touch.location(in: scnView)
 let hitResults = scnView.hitTest(location, options: nil)
 if let result = hitResults.first {
      handleTouchFor(node: result.node)
     }
  }

func handleTouchFor(node: SCNNode) {
  if node.name == "ThreeDShape" {
         print("SCNNode Touched")
    }
  }
}

这是我的Spritekit叠加场景

import Foundation
import SpriteKit

class spritekitHUD: SKScene{

var game:GameViewController!
var shapeNode: SKSpriteNode!

init(size: CGSize, game: GameViewController){
    super.init(size: size)
    self.backgroundColor = UIColor.white

    let spriteSize = size.width/12
    self.shapeNode= SKSpriteNode(imageNamed: "shapeNode")
    self.shapeNode.size = CGSize(width: spriteSize, height: spriteSize)
    self.shapeNode.position = CGPoint(x: spriteSize + 8, y: spriteSize + 8)
    self.shapeNode.name="test"
    self.game=game


    self.addChild(self.pauseNode)

}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch=touches.first else{
        return
    }
    let location=touch.location(in: self)
    if self.atPoint(location).name=="test" {
     print("Spritekit node pressed")
    }
 }
}

所以有了这个,我可以成功收到我的overlaySKScene上已经触及我的spritenode的通知,但是我无法弄清楚如何获得我的SCNode被触摸的通知。如果你不能有2个触摸功能,那么任何人都有任何想法如何同时处理2d事件的3D事件吗?

感谢您的帮助!!

3 个答案:

答案 0 :(得分:6)

如果您想使用SKScene的{​​{1}}叠加层进行用户控制,(例如,您希望在SKScene叠加层中实现一个&#34;消耗&#34;触摸)的按钮,但也有触摸不要触及控件以通过并注册基础SCNView,你必须这样做:在SKScene叠加层上设置SCNViewisUserInteractionEnabled本身,但然后false对于您希望充当按钮的叠加层中的任何单个元素。

true

如果用户触摸按钮,则按钮的触摸事件(let overlay = SKScene(fileNamed: "overlay") overlay?.isUserInteractionEnabled = false let pauseButton = overlay?.childNode(withName: "pauseButton") as? Button // Button is a subclass of SKSpriteNode that overrides touchesEnded pauseButton?.isUserInteractionEnabled = true sceneView.overlaySKScene = overlay touchesBegan等)将触发并消耗触摸(基础手势识别器虽然仍然开火)。但是,如果他们触摸按钮外,触摸将传递到底层SCNView。

答案 1 :(得分:4)

直接从Xcode的游戏模板中“解除”......

在viewDidLoad中添加手势识别器:

       // add a tap gesture recognizer
       let tapGesture = UITapGestureRecognizer(target: self, action:  
           #selector(handleTap(_:)))
        scnView.addGestureRecognizer(tapGesture)

    func handleTap(_ gestureRecognize: UIGestureRecognizer) {
    // retrieve the SCNView
    let scnView = self.view as! SCNView

    // check what nodes are tapped
    let p = gestureRecognize.location(in: scnView)
    let hitResults = scnView.hitTest(p, options: [:])
    // check that we clicked on at least one object
    if hitResults.count > 0 {
        // retrieved the first clicked object
        let result: AnyObject = hitResults[0]

        // result.node is the node that the user tapped on
        // perform any actions you want on it


    }
}

答案 2 :(得分:0)

您可以在spritekitHUD中实现此方法:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
{
   game.touchesBegan(touches, with: event)
}