Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance Issues #18

Open
technicallyerik opened this issue Jun 1, 2018 · 5 comments
Open

Performance Issues #18

technicallyerik opened this issue Jun 1, 2018 · 5 comments

Comments

@technicallyerik
Copy link
Contributor

I recently updated from 1.12 to 1.16 and am seeing some significant performance issues. From around 5% CPU and 60 FPS (v1.12) to 100% CPU and 5 FPS (v1.16).

This performance drop appears to be because of the work in update on SKTile. I don't want to set tilemap.isPaused = true because I have other animations I want to run. But at rest, none of my tile map animates.

@mfessenden
Copy link
Owner

Wow, that is significant.

Out of curiosity, what are your map stats (map size, tile size, # of animated objects)? I haven't seen performance drops on this end, but I don't think my test maps are pushing the CPU too much.

Also, how are you testing the CPU usage currently? I want to see if I can reproduce the performance drop on my end. If you feel comfortable sending me files, I'll can run some tests on them here.

Prior to 1.16, tile animations were run with SKAction actions, which are very efficient, but have two major deficiencies:

  • actions can't be modified after running; sprites can be paused, but timing changes are impossible
  • actions all run independently, so frames can easily get out of sync

I had a request to change this behavior for a game in development, and the result allows you to dynamically slow down/speed up the map dynamically, or even reverse the tile animations. We didn't see any major performance issues, so I made that version public. I am finishing a new release for Swift 4.0 & AppleTV support right now, so I could add a fix to run tile animations via actions again if that'll help.

@technicallyerik
Copy link
Contributor Author

technicallyerik commented Jun 2, 2018

I took the above on the simulator. On a device, it looks like the FPS is better, but the CPU usage is still very high.

For our scene... the debugging text says there are 126 nodes. Tiles are 150px by 130px hex tiles, and the map I loaded was only 10 x 10 tiles. None of our objects are animated at "rest", where the CPU is still high. The only animations that happen are in response to user interactions.

You can see the difference in the built in demo app looking at the debug pane. These numbers are from a physical iPhone 7, showing the dungeon map. I'm not interacting with the map at all.

1.12
1 12

1.16
1 16

@mfessenden
Copy link
Owner

There are new options for tailoring performance in the 1.2 release. I'm still updating the docs, but tilemap node now has a propery updateMode that controls how tiles are rendered:

// set the map's update mode to `dynamic`
tilemap.updateMode = TileUpdateMode.dynamic

// instantiate a tilemap to render animated tiles with SpriteKit actions
let tilemap = SKTilemap.load(tmxFile: "my-tilemap", updateMode: TileUpdateMode.actions)!

The default mode is dynamic, which only updates tiles as needed (ie. animated tiles, tiles with changed tile data) and generally uses less than half the CPU usage of the 1.16 version. If you want to use SpriteKit actions, there is also an actions mode. You're also free to change the update mode at any time... the map will adjust accordingly.

I've also exposed several previously internal API methods that allow you to manually stop & start tile animations using SpriteKit actions in case you want to just leave the tilemap node out of the SKScene.update loop and control animations yourself:

// run all tile animations as SpriteKit actions
tilemap.runAnimationAsActions(true)

// remove actions for all layers/tiles/objects (optionally restoring the tile's original texture)
tilemap.runAnimationAsActions(false, restore: false)

// run tile animations with a SpriteKit actions in a layer
layer.runAnimationAsActions()

// remove tile animation actions in a layer
layer.removeAnimationActions(restore: false)

// run tile animation with a SpriteKit action
tile.runAnimationAsActions()

// remove tile animation action
tile.removeAnimationActions(restore: false)

Hope that helps a bit, if there are any questions, feel free to ask.

@technicallyerik
Copy link
Contributor Author

I dropped 1.2 into my project and still run into issues.

When the SKTilemap.load callback is called, I programmatically create a handful of tile layers via tilemap.newTileLayer. Going from the 6th -> 7th new tile layer appears to cause CPU to go from 1% at rest to 100% at rest. This is after removing any code that uses the tile layers. The CPU also remains high even if I set isPaused to true.

I'm struggling to track down the cause of the issue in the framework.

@mfessenden
Copy link
Owner

Is there any code that you can share that illustrates what's happening? I'm not able to reproduce that here with the devices I'm testing on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants