iosswiftxcodeskspritenodesknode

Why does Xcode TouchesEnded() topMost touched node always return child nodes rather than the parent node?


I have Subclassed SKSpriteNode as a MenuButton()

The MenuButton() contains 2 children:

When the below runs, if the user touches part of the button containing the image or the text (the children of the MenuButton() ), it doesn't execute as the image/text have a different name to the button and they are the first touchedNode.

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

        guard let touch = touches.first else { return }
        let location = touch.location(in: self)
        let touchedNode = atPoint(location)
        let touchedNodeName = atPoint(location).name

        if let nodeName = touchedNodeName, nodeName == ("btnPlay") { self.showGameModeMenu() }
}

Previously, I used:

let touchedNodes = nodes(at: location)
for node in nodes {
    if let nodeName = node.name, nodeName == "btnPlay" { self.showGameModeMenu() }
}

However, when another node (btnCloseLeaderboard) is presented over the top btnPlay, it loops through and executes both rather than just the top-most node (btnCloseLeaderboard)

I've attempted to set isUserInteractionEnabled = false for the child nodes but that doesn't work. It still sees then as the topmost node.

How do I prevent this from happening?


Solution

  • It sounds like you to want to show the game menu if the name of a child's parent is "btnPlay" or if the node named "btnPlay" is tapped itself (for taps outside the image or text children). If so, you can change your top code to this:

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        let location = touch.location(in: self)
        let touchedNode = atPoint(location)
        if touchedNode.parent?.name == "btnPlay" || touchedNode.name == "btnPlay" { showGameModeMenu() }
    }