Skspritenode Does Not Let Touches Pass Through When Isuserinteractionenabled False

SKSpriteNode does not let touches pass through when isUserInteractionEnabled false

You need to be careful with zPosition. It is possible to go behind the scene, making things complicated.

What is worse is the order of touch events. I remember reading that it is based on the node tree, not the zPosition. Disable the scene touch and you should be seeing results.

This is what it says now:

The Hit-Testing Order Is the Reverse of Drawing Order In a scene, when
SpriteKit processes touch or mouse events, it walks the scene to find
the closest node that wants to accept the event. If that node doesn’t
want the event, SpriteKit checks the next closest node, and so on. The
order in which hit-testing is processed is essentially the reverse of
drawing order.

For a node to be considered during hit-testing, its
userInteractionEnabled property must be set to YES. The default value
is NO for any node except a scene node. A node that wants to receive
events needs to implement the appropriate responder methods from its
parent class (UIResponder on iOS and NSResponder on OS X). This is one
of the few places where you must implement platform-specific code in
SpriteKit.

But this may not have always been the case, so you will need to check between 8 , 9, and 10 for consistency

spritekit make childnode not touchable

You have to implement touchesBegan in a subclass of SKSpriteNode and to set its isUserInteractionEnabled = true, in order to accept and process the touches for that particular node (button).

import SpriteKit

protocol ButtonDelegate:class {

func printButtonsName(name:String?)
}

class Button : SKSpriteNode{

weak var delegate:ButtonDelegate?

init(name:String){
super.init(texture: nil, color: .purple, size: CGSize(width: 250, height: 250))
self.name = name
self.isUserInteractionEnabled = true
let icon = SKSpriteNode(color: .white, size: CGSize(width:100, height:100))
addChild(icon)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

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

delegate?.printButtonsName(name: self.name)
}
}

class GameScene: SKScene, ButtonDelegate {

override func didMove(to view: SKView) {

let button = Button(name:"xyz")
button.delegate = self

button.position = CGPoint(x: frame.midX - 50.0, y: frame.midY)

addChild(button)

}

func printButtonsName(name: String?) {

if let buttonName = name {
print("Pressed button : \(buttonName) ")
}
}
}

Now, this button will swallow the touches and the icon sprite will be ignored.

I just modified the code from one of my answers to make an example specific to your needs, but you can read, in that link, about whole thing more in detail if interested.

Turn off touch for whole screen, SpriteKit, how?

There is no global method to turn off the touch, whatever is at the top of the drawing queue is the first responder.

You need to iterate through all of your nodes from your scene and turn them off:

enumerateChildNodesWithName("//*", usingBlock: 
{ (node, stop) -> Void in
node.isUserInteractionEnabled = false
})

Now the problem is turning them back on, if you use this method, you will turn it on for everything, so you may want to adopt a naming convention for all your touchable sprites

enumerateChildNodesWithName("//touchable", usingBlock: 
{ (node, stop) -> Void in
node.isUserInteractionEnabled = true
})

This will look for any node that has a name that begins with touchable.

This method involves recursion, so if you have a ton of nodes, it can be slow. Instead you should use an alternative method:

let disableTouchNode = SKSpriteNode(color:SKColor(red:0.0,green:0.0,blue:0.0,alpha:0.1),size:self.size)
disableTouchNode.isUserinteractionEnabled = true
disableTouchNode.zPosition = 99999
self.addChild(disableTouchNode)

What this does is slap on an almost transparent node on top of all elements the size of the scene. This way when a user touches the screen, this node will absorb it instead of anything else.

swift/scenekit problems getting touch events from SCNScene and overlaySKScene

This is "lifted" straight out of Xcode's Game template......

Add a gesture recognizer in your 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

}
}


Related Topics



Leave a reply



Submit