5

I'm doing, what I think, is a very simple timer bar, with nothing else on the screen. Yet this can't maintain 60fps on an iPad Pro... am I doing something obviously heavy and wrong?

let previewTime: TimeInterval = 3.0

func timerBar(){

    let tbW: CGFloat = frame.size.width / 2
    let tbH: CGFloat = 64
    let tbSize = CGSize(width: tbW, height: tbH)

    let timerBox = SKSpriteNode(color: SKColor.black, size: tbSize)
    timerBox.anchorPoint = CGPoint(x: 0.0, y: 0.0)
    timerBox.position = CGPoint(x: frame.size.width / 2 - (tbW / 2), y: 500)
    timerBox.zPosition = 8
    addChild(timerBox)

    let timerBoxBar = SKSpriteNode(color: .white, size: tbSize)
        timerBoxBar.anchorPoint = CGPoint(x: 0.0, y: 0.0)
        timerBoxBar.position.x = 0.0
        timerBoxBar.position.y = 0.0
        timerBoxBar.xScale = 0.0
    timerBox.addChild(timerBoxBar)

    let animPreviewTime = SKAction.scaleX(to: 1, duration: GameScene.previewTime)
    timerBoxBar.run(animPreviewTime){self.randomisePositions()}
}

This makes a timer bar with a black background and a white timer bar, that animates across the screen for 3 seconds, until the timer bar is full.

It stutters, visibly, and instruments show it using up spikey blue moments of rendering, sufficient to consistently make it stutter.

Update

Here's the spikes during the rendering of this, as you can see, either side of the time bar animation, absolute NOTHING is happening:

enter image description here

Xcode Version 8.2 beta (8C23)

iOS 10.2 Beta 2

Downloading iOS 10.2 beta 3 now...

Confused
  • 6,048
  • 6
  • 34
  • 75
  • 1
    are you doing this on a real ipad pro? the simulator is a mess on even the newest mac devices – Knight0fDragon Nov 16 '16 at 20:38
  • what KOD said.. Also, where are you calling this func... – Fluidity Nov 16 '16 at 21:10
  • Yes, real iPad Pro. There's no way I'd ever test anything in the Simulator. @Knight0fDragon – Confused Nov 16 '16 at 21:26
  • This function is called inside didMove(to view...) in the current scene. @Fluidity – Confused Nov 16 '16 at 21:26
  • What's happening in your update() function whilst this timer bar is doing it's thing? – Steve Ives Nov 16 '16 at 21:28
  • @SteveIves nothing at all in update function. Airport mode on, WIFI and BlueTooth off. No other apps in background, nothing bring printed to console. – Confused Nov 16 '16 at 21:32
  • 1
    @Confused you should try this on a stable version of Xcode and iOS. – Fluidity Nov 16 '16 at 21:48
  • @Confused you can override all of the `didFinish` methods and put a timer function in there to see which part of the SK cycle is hanging. – Fluidity Nov 16 '16 at 21:48
  • @Fluidity I'm a designer. So my comprehension of code is absolutely minimal. I've assumed I'm doing something wrong. I'd love to override `didFinish` but I have no idea what you're talking about. Sorry. – Confused Nov 16 '16 at 21:50
  • @Confused your code looks good, but I'm not sure about the `randomisePositions` you should post that func here too. Also, here is what I'm talking about.. you can override all of those `did` functions listed here: https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html It may be that you are running on Betas all around – Fluidity Nov 16 '16 at 21:51
  • btw, have also reduced height of the bar from 64 to 2 units, and that's made no difference. – Confused Nov 16 '16 at 21:52
  • @Confused lag spikes can happen at any one of those steps I linked you... When one of those steps takes longer than it's supposed (the whole cycle takes like .016 seconds 1/60th of a second) then laggy things happen. In other words, if your taking 4-5 times longer in one of those steps than you are supposed to, then you will get a lag spike. So by checking the time in each one of those methods, and comparing it to the previous step's time, you can instantly find out where in the SK update cycle that your lag is happening... – Fluidity Nov 16 '16 at 21:55
  • @Fluidity `randomisePositions` is correctly not getting called until after the timerBar finishes, and despite having quite a lot in it, doesn't register even a blip in the instruments, nor cause any stuttering. Works perfectly. In another function, I'm making 72 objects that do a similar scaling of themselves, all SKSpriteNodes, and they don't ever drop from 60fps, and can be replicated so there's 1000's of objects onscreen without a drop, too. – Confused Nov 16 '16 at 21:56
  • argh, @Fluidity, I see what you're on about. There's literally nothing else happening in any of the updates of the gameloop. This is an absolutely isolated timer bar, the entire app is doing nothing while this happens, hence the grey bars in the screenshot added to the question on either side of the timer bar. There's not even a CPU spike showing for the randomPositions function, it's so trivial. I can comment it out, and same problem. – Confused Nov 16 '16 at 21:59
  • @Confused it really sounds like a beta / simulator issue :p. There's nothing in your code to indicate something crazy – Fluidity Nov 16 '16 at 22:02
  • It's very comforting, @Fluidity that I'm not doing anything wrong. That's a bit of a first, I think. – Confused Nov 16 '16 at 22:08
  • @Confused what I do in these situations is #1, use a stable version, then #2, make a new project and replicate JUST that one thing. Xcode / computer sometimes need to be restarted / reinstalled. I tried XC8 beta every release for about 5 mins then uninstalled it was so buggy. Also, you *should* test it in the simulator as well, because more info is always good in problem solving – Fluidity Nov 16 '16 at 22:10
  • @Confused NP. Like I said, when you start banging your head on the wall, start a new project and isolate :) Glad you found it – Fluidity Nov 16 '16 at 22:38
  • @Fluidity also found a bug. Set the xScale of the SKSpriteNode to 0 before firing the action, and it never scales. Set it to 0.001, and it's fine. Also, I think the effectNode re-rendering when there's no conflict is probably also a bug. or buggy. I tried that on a whim. – Confused Nov 16 '16 at 22:45
  • @Fluidity, but yes, there is a sizeable hole in the wall and a flatter part of my head, now. – Confused Nov 16 '16 at 22:46
  • well of course setting scale to 0 won't scale, it is based on multiplication, anything times 0 would yield a result of 0 – Knight0fDragon Nov 17 '16 at 01:26
  • @Confused you should answer your own question so it will show up as resolved for others who look at this :) – Fluidity Nov 17 '16 at 19:51
  • @Knight0fDragon nonsense. This has nothing to do with that. This is a bug. Setting the scale is only a state, not a removal of the object's scale or size. – Confused Nov 17 '16 at 20:49
  • @Fluidity soon... – Confused Nov 17 '16 at 20:49
  • What? First of all starting at a scale of 0 makes absolutely no sense, logically speaking. Nothing in our world exists with a width and height of zero. You are trying to scale from non existence to 1. Second, scale is all about multiplication, this is the driving force behind it, a width of 1 scaled by 2 = 2. 1 x 2 = 2. Third, when the only problem with math is due to a zero, then there is a good change you know it is a multiplication problem because zero times anything yields zero, meaning you will never be able to progress. – Knight0fDragon Nov 17 '16 at 21:09
  • You still aren't getting it. Scale, as operation upon a SpriteKit SKSpriteNode is an animation operation. The reason to scale from zero is so that it's not there, and then it becomes there... and grows over time. Setting the xScale of SKSpriteNode to 0.001 shouldn't work, either, if what you're saying applied. – Confused Nov 17 '16 at 21:17
  • why would setting scale to .001 not work? 10 * 0.001 = 0.01. The scaleTo action is doing xScale *= some formula per iteration. This means your xScale can never change to a new value. You then could create potential problems where you hit NaN situations, and who knows what apple does to handle this stuff, which is what may be blowing up your CPU usage – Knight0fDragon Nov 17 '16 at 21:47

0 Answers0