Still no way to create a 'fall through' layer

I am working on a sudoku game, and simply want to outline the boxes with a top layer.


The only job of this top layer is to create visible black lines. I don't want it to be touchable at all...


Is there anyway to create a fallthrough layer? A full screen node with the highest zPosition, but has no touch.


If I attempt to do this, all I get is a top layer that captures all touches and makes the game unplayable.


I remember seeing a thread on this years ago. Has Apple fixed it?


Thanks for any help!


ANDY

Replies

sprite.isUserInteractionEnabled = false doesn't work, unless I want to cancel touches out for the entire Game Scene node.


This is the last remnant, and pretty much only one now, that I miss from cocos2d. Touches fell through layered nodes. That was the default.


If I want to set up a node to block all touches, I should have to do it specifically not be the default behavior.


I am not going to play with this anymore. Forget it. No black lines. It will just be a color grid.


But this a real inconvienence.



Birkenmose where are you? LOL.


But thanks QuincyMorris for the help! You have helped me out in the past, I hope to be able to return the favor!

Yeah, I feel your pain. I've been complaining about this for years now, also having moved from Cocos2D to SpriteKit. This thread is from two years ago and in it I complain about being annoyed for already a year: https://forums.developer.apple.com/message/214626. So it's been at least three years already 😀.


As I report in the thread linked above, this behavior changed with iOS 8, then with iOS 9, then again with iOS 10. At least now I don't have to worry about inconsistency (because I don't support iOS 9 anymore, really), but the problem still persists. There is no sense why nodes would block touches by default, and there's even less sense in not having a way to opt out of it.


I have encountered this problem in a number of things, usually having to do with nodes that I hide periodically. For example, I have a custom blocker class, which acts as a touch blocker when activated. Since I can do nothing to have it NOT block touches, I either move it out of screen or make it (0, 0) in size when it's not supposed to be active. Resizing to zero of course becomes a problem when you have content in the node, so in those cases the only option is to move the node away from the frame, which makes me feel like I'm developing software in 1995.


The biggest problem I have is with creating objects that swipe between selections (think of a button that has a SKCropNode and scrolling content inside). All of the scrolling content that is hidden beyond the cropping is blocking touches. Now, you can always code interactions to not react outside of the masked area, but the area outside the mask is still gonna swallow touches. In an app with multiple scrolling windows at the same time (think for example a hacking simulator game), you would have to very smartly switch zPositions based on where you touch. And if you wanted multitouch, sorry, it's impossible (at least with object-oriented structures).


I really don't know what to do at this point. Should we band together and send a signed letter or something 😀?

Hello,


Here is a way that you could create a "fallthrough layer":


Inside of your SKScene sub-class, override touchesBegan and insert:


for node in self.nodes(at: touch.location(in: self)) {
  // insert logic to ignore your "fallthrough" node here.
  // respond to the touch on the node that you actually wanted to touch here.
}

With respect, herein lies the issue. If you were to handle all touch detection only in the SKScene class, that would make it easier to determine which node should receive the touch. However, in any complex system, you would (at least in my opinion) distribute touch handling to objects themselves.


For example, I have a Button class that I use in all my projects, which is subclassed from SKNode. Button receives and handles its own touches, so that such logic doesn't have to be repeated multiple times in each SKScene, in each project. Buttons tend to be important elements, so you're likely to find one in each SKScene in your project, making it highly efficient to offload this particular logic to the object class. So when I want to use a button, I instantiate Button in an SKScene, feed it the functionality I want it to perform upon touching and it works out of the box.


Since touch handling is distributed, you can't really loop through and consider touch fallthrough per node. Consider a custom scroll view class, which you want to use on three areas of one SKScene (like the hacker game I mentioned in my earlier post). You wouldn't want to handle those scroll view's internal workings, including drag, deceleration and bounce, for each instantiation in a SKScene, for each SKScene in a project and for each project, would you?