Delay Responding to First Touch

I converted the prototype of a word game from OS X to iOS. The iOS version works well except for one problem. When I launch the game and touch a letter tile for the first time, there's a 3-5 second delay before the touch is registered and the tile I touched gets highlighted. After the first touch, every other touch registers without any delay.


My first thought was that the delay was caused by the word list taking too long to load, keeping the game from responding to player input. But the delay persists even if I wait 20-30 seconds after launching the game to start touching letter tiles.


I profiled the game with the Time Profiler instrument in Instruments, and the CPU percentage shoots up from 40% to 99% on the first touch. Later touches increase the CPU load to 50-60%. Looking at the call tree, all the time is spent in the touchesBegan function. Here's my touchesBegan code:


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        / Called when a touch begins */
       
        for touch in touches {
            let location = touch.locationInNode(self)
            // Determine the tile that was touched.
            if let clickedTileNode = nodeAtPoint(location) as? SKSpriteNode {
                handleTileClick(clickedTileNode)
            }
           
            // Check for button touches.
            if let clickedButtonNode = nodeAtPoint(location) as? SKLabelNode {
                handleButtonClick(clickedButtonNode)
            }
           
        }
    }


When I make the first touch, Instruments says 100% of the time is spent in line 12. I changed the if statement in line 12 to an else-if statement, and the initial delay persists.


How do I get the first touch to register without the 3-5 second delay?

Hi szymczyk,


Thanks for posting. Without knowing more about your project it is hard to guess at what the issue may be. The first thing to investigate is just how large the scene is in terms of nodes on the first call to nodeAtPoint. If the sceen is dramatically reduced after calling handleTileClick or handleButtonClick then that would account for the first versus subsequent call cost.


One small thing to at least halve the cost is to change your code to read more like:


let location = ...

let node = nodeAtPoint(location) //call it only once


if let clickedTileNode = node as? SKSpriteNode {

...

}


if let clickedButtonNode = node as? SKLabelNode {

...

}



The call to nodeAtPoint will go through all the children and find a node that is in the location. Its running cost is highly dependent on the number of nodes it has to search. Also if you have a lot of shape nodes in your scene it may be the first time they are determining their exact bounds and that can take a short one-off duration per node. Yet again it is relative to complexity. If you have quads as shape nodes it is always faster to use sprite nodes instead.


Feel free to file a bug report with a test project attached if you want more detailed feedback.


Cheers

Thanks for the tip on how to reduce the calls to nodeAtPoint(), but the delay is still there.


The scene has 279 total nodes, according to the debugging information in the scene. There are 256 sprite nodes representing the game board with the rest being sprite and label nodes. 279 nodes doesn't sound like a big enough scene to cause a delay on an iPad 3 (the first retina model) running iOS 9.0.2.

Hi szymczyk,


Thanks for trying out the most basic changes. In order to make a more educated guess we'd need to see the sample in action. Please file a bug report that contains your sample and post the bug nubmer back here. We can triage the sample and let you know why you are seeing the issue and possibly provide you with a workaround.


Cheers

I filed the bug report: Bug #23343650.

Hi szymczyk,


Thanks for posting a sample with your bug report. Using your sample we can see a small spike for the first call, but that seems due to the first time the nodes in the scene need to accumulate their bounds for a bounds test against a point. That is a one off cost, so that does make sense as a spike. We are not able to see a 2-3 second delay however. Which device did you experience this on?


Cheers

I'm experiencing the delay on an iPad 3 running iOS 9.0.2.

I'm experiencing the same problem. I have a skscene (my main menu) with 3 sknodes that upon touching a button presents another scene with less than 24 sknodes. After launching the app, the first time the button is pressed from the menu, there is an approx 2 second delay. After that there is no longer a delay. I'm using an iPhone 5s running 9.1. This also occurs in the iPhone Simulator, although the delay is only about a .5 second delay. I can provide video upon request.

Hi canadiandeveloper,


Getting more information always helps. While we are not able to reproduce this with 9.2 beta we would like to know if the isse is with SKNode.containsPoint or something else in the system. As I mentioned before we see a small spike in traces when calling it the first time, though not large enough to cause delays.


Would you be able to try calling SKNode.containsPoint during your app launch after the level loads or your menu is shown, after the scene is setup and ready. If the calculation of accumulated frames is the problem that should remove a first time hit from a touch.


Please let us know if that makes a difference as it lets us know if containsPoint is the issue or just a red-herring.


Cheers

Delay Responding to First Touch
 
 
Q