1

So I ran into a problem with lag on a platformer game I'm building. So I'm researching how to improve performance.

I'm trying to do batch drawing, so that there is less draw calls. I'm having issues though. So with a brand new project:

I have 4 hero sprites, all images are stored in a .atlas folder. so there is a 1/2/3x image for each sprite in the atlas folder.

I drag and drop that into the xcassets folder. Then I go to my sks file create 4 sprites and change the texture accordingly.

By default they all have the same blend mode. I have the default rule set to true for ignoring sibling order. All sprites are on the default z 0 layer. and I have it set to show draw count.

I would expect to see 1 draw since all images are in the same atlas file, but I see 4.

Is there something I'm missing?

Just curious how I get this to work properly. Thanks for any help!!!

Discoveringmypath
  • 1,049
  • 9
  • 23

1 Answers1

1

There was a bug with xcassets on iOS 9 where draw calls wouldn't be reduced even if images were placed in xcassets. Apparently that was fixed with later versions, but since then I never bothered with xcassets. Instead I place images in a seperate .atlas folder in the project, which does reduce the draw calls.

Try to place 4 sprites with the same texture and see what the draw calls are then. It shouldn't be 4 if the sprites are using the same texture. I would also suggest to add 8 sprites (4 different textures * 2 sprites each) and see if the draw calls increase to 8.

If the draw calls don't increase, then I would assume that 4 draw calls is what it takes to draw your 4 different sprites (if they are very complex ones). If the draw calls do increase, try removing the images from xcassets and place them into a seperate .atlas folder in your project, and compare draw calls then.

JohnV
  • 981
  • 2
  • 8
  • 18
  • Thanks for the comments. I have tested with the atlas folder instead of the xcassets as well and I get the same results. If I use the same image, then the count does drop to 1. I was under the impression that if images were in the same atlas file, then it would only take one draw call. My images are not that complicated either. – Discoveringmypath Jun 11 '17 at 04:29
  • Here is a link to an Apple video that talks about the batching: https://developer.apple.com/videos/play/wwdc2014/608/ . If you jump to 20-22 min, it talks about it. – Discoveringmypath Jun 11 '17 at 04:32
  • If the draw count did drop to 1 with many sprites with the same image, then I guess it's working properly. My (basic) understanding is that there will be 1 draw call per texture. But if you have, say 40 sprites, 10 sprites each with a different texture, draw counts would still only be 4, since the same texture is reused. – JohnV Jun 11 '17 at 04:40
  • So the batching is free. If I don't use a atlas file, same thing will occur. 4 of the same textures will draw only 1 time. But the purpose of the atlas file is to combine all the images into 1 sprite sheet, that you should only need to call draw 1 time. At least that is what I keep reading about and that video demonstrates. Just thought maybe I'm missing something... – Discoveringmypath Jun 11 '17 at 04:45
  • 1
    Looked at the video now - maybe I'm missing something too... In my spritekit games, I get one draw call per texture used (using .atlas folder), Even when testing at extremes where there are 1000 nodes, I get about 25 draw calls for all the nodes, which use different textures. Performance is still good with 25 draw calls at 59.something FPS. Maybe someone else can shed light on this because maybe the approach I'm using is not really optimal and could easily be fixed.... – JohnV Jun 11 '17 at 05:07
  • 1
    Ya hopefully, I'm very curious on if I should keep searching for an answer or move on... – Discoveringmypath Jun 11 '17 at 05:18
  • 1
    As a side note: another thing for optimization that I do is to create SKTextures from the images first, and then create SKSpriteNodes from the textures (instead of let node = SKSpriteNode(imageNamed:) I use let node = SKSpriteNode(texture: ). I keep the textures in memory for later use. That way you only load the texture once into memory, and not need to reload it when you create a new sprite with the same image. – JohnV Jun 11 '17 at 05:25
  • Thanks for the tip, I'll keep that in mind for when I reach that stage. – Discoveringmypath Jun 11 '17 at 05:41
  • The atlas folder works currently. I'm not sure if Apple has fixed the issue at this time as I'm just using atlas folders, but this answer is correct. – Discoveringmypath Nov 15 '17 at 15:32
  • I'm using a 'spriteatlas' (as they appear to be called now), and I'm seeing a big difference in performance between an actual device (iOS 12 iPhone 6) and Simulator (iOS 13.3). On the device, I get 1 draw call. In the simulator, I get as many draw calls as the number of unique textures being used, even though all textures share the same atlas. The Simulator frame-rate also tanks. – Womble Jul 18 '20 at 00:44