swift/scenekit 从 SCNScene 和 overlaySKScene 获取触摸事件时出现问题
swift/scenekit problems getting touch events from SCNScene and overlaySKScene
下午好,我正在尝试弄清楚如何从 SCNNode 和 SKSpriteNode 从覆盖有 SKScene 的 SCNScene 获取触摸通知。
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")
}
}
}
因此,我可以成功地收到有关我的 spritenode 已在我的 overlaySKScene 上被触摸的通知,但我无法弄清楚如何收到我的 SCNode 已被触摸的通知。如果你不能有 2 个 touchesbegan 函数,有没有人知道如何同时处理 3d 事件和 2d 事件?
感谢您的帮助!!
这是"lifted"直接来自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
}
}
你可以在spritekitHUD中实现这个方法:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
game.touchesBegan(touches, with: event)
}
如果您想使用 SCNView
的 SKScene
叠加层用于用户控件,(例如,您想在 SKScene 叠加层中实现一个 "consumes" 触摸的按钮),但也有不点击控件的触摸以通过并在底层 SCNView
中注册,您必须这样做:在 SKScene 叠加层本身上将 isUserInteractionEnabled
设置为 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
、touchesEnded
等)将触发并消耗触摸(底层手势识别器将 仍然开火)。但是,如果他们触摸按钮外部,触摸将传递到底层 SCNView。
下午好,我正在尝试弄清楚如何从 SCNNode 和 SKSpriteNode 从覆盖有 SKScene 的 SCNScene 获取触摸通知。
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")
}
}
}
因此,我可以成功地收到有关我的 spritenode 已在我的 overlaySKScene 上被触摸的通知,但我无法弄清楚如何收到我的 SCNode 已被触摸的通知。如果你不能有 2 个 touchesbegan 函数,有没有人知道如何同时处理 3d 事件和 2d 事件?
感谢您的帮助!!
这是"lifted"直接来自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
}
}
你可以在spritekitHUD中实现这个方法:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
game.touchesBegan(touches, with: event)
}
如果您想使用 SCNView
的 SKScene
叠加层用于用户控件,(例如,您想在 SKScene 叠加层中实现一个 "consumes" 触摸的按钮),但也有不点击控件的触摸以通过并在底层 SCNView
中注册,您必须这样做:在 SKScene 叠加层本身上将 isUserInteractionEnabled
设置为 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
、touchesEnded
等)将触发并消耗触摸(底层手势识别器将 仍然开火)。但是,如果他们触摸按钮外部,触摸将传递到底层 SCNView。