Skip to content

Instantly share code, notes, and snippets.

@brynbodayle
Created February 14, 2019 04:20
Show Gist options
  • Save brynbodayle/46a6baeb575070f6e9bfc48371c74d23 to your computer and use it in GitHub Desktop.
Save brynbodayle/46a6baeb575070f6e9bfc48371c74d23 to your computer and use it in GitHub Desktop.
SKScene UserInteraction Bug Fix
//
// Original Objective C version: https://gist.github.com/bobmoff/7110052
//
// Fix SpriteKit's SKNode bug on iOS 7 & 8: nodes capture touch events
// even when userInteractionEnabled is false and the nodes are hidden.
//
// Details:
// http://stackoverflow.com/questions/19511334/sprite-with-userinteractionenabled-set-to-yes-does-not-receive-touches-when-cove
//
// How to use:
// Use SKSceneWithUserInteractionBugfix class in place of SKScene.
//
import SpriteKit
extension SKNode {
func nodeDepthPriority() -> String {
var code = ""
var currentNode = self
while let parent = currentNode.parent {
var idx = 0
for obj in parent.children {
if obj == currentNode {
code = NSString(format: "%03d%@", idx, code) as String
break
}
idx += 1
}
currentNode = parent
}
return code
}
}
extension SKScene {
func nodeWithHighestPriority(_ touches: Set<UITouch>) -> SKNode? {
// Only allow touches to be receieved by nodes with userInteractionEnabled, and only the one with the highest touch priority
guard let touch = touches.first else { return nil }
let touchLocation = touch.location(in: self)
let touchedNodes = nodes(at: touchLocation)
var nodeToTouch: SKNode!
for node in touchedNodes {
if node.isUserInteractionEnabled && !node.isHidden && node.alpha > 0 {
if nodeToTouch == nil {
nodeToTouch = node
} else if node.parent == nodeToTouch.parent && node.zPosition > nodeToTouch.zPosition {
nodeToTouch = node
} else if node.parent == nodeToTouch.parent && node.zPosition == nodeToTouch.zPosition && nodeToTouch.nodeDepthPriority().compare(node.nodeDepthPriority()) == .orderedAscending {
nodeToTouch = node
} else if node.parent != nodeToTouch.parent && nodeToTouch.nodeDepthPriority().compare(node.nodeDepthPriority()) == .orderedAscending {
nodeToTouch = node
}
}
}
return nodeToTouch
}
}
extension SKScene {
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let nodeToTouch = nodeWithHighestPriority(touches)
nodeToTouch?.touchesBegan(touches, with: event)
}
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let nodeToTouch = nodeWithHighestPriority(touches)
nodeToTouch?.touchesEnded(touches, with: event)
}
open override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
guard let touches = touches else { return }
let nodeToTouch = nodeWithHighestPriority(touches)
nodeToTouch?.touchesCancelled(touches, with: event)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment