3

I am curious if anybody has been able to figure out a way to keep how long a scene has been active for. This is critical for when I need to fire certain events, like say "spawn ship 5 minutes into game play".

The issue with the update cycle, is that the current time being passed is not active game time only, so if you get a call or switch apps, upon return you will get that X minute jump in time.

Currently, I use an SKAction.customAction to keep track of my time, and it works, but I cannot guarantee the order in which actions fire, so my events could end up being 1 frame off.

Here is what I am doing now, please let me know what you have done to keep time consistent.

//Note: NodeComponent is a protocol extension to quickly access the GKSKNodeComponent's node

import GameplayKit
class ElapsedTimeComponent:GKComponent,NodeComponent
{
    var elapsedTime : TimeInterval = 0.0
    override func didAddToEntity() {
        node.scene?.addComponentToComponentSystem(self)
        self.node.run(SKAction.customAction(withDuration:330000000000000000000000000000000000000){node,seconds in
            elapsedTime = seconds
            (node as! SKLabelNode).text = "\(seconds)"
        })

    }
    override func update(deltaTime seconds: TimeInterval) {
    }
}
Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44

1 Answers1

2

So it turns out, SKView has a delegate protocol you can attach anywhere. I have set up my latest test to look like this:

public class GameScene: SKScene,SKViewDelegate {
    var previousTime : TimeInterval = 0
    var gameTime : TimeInterval = 0
    public func view(_ view: SKView, shouldRenderAtTime time: TimeInterval) -> Bool
    {
        if !self.isPaused{
            gameTime += time - previousTime
        }

        print("GameTime: \(gameTime)")
        componentSystems.forEach({$0.update(deltaTime: gameTime)})
        self.previousTime = time
        return !self.isPaused
    }
    public override func didMove(to view: SKView) {
        view.delegate = self     
    }
}

https://developer.apple.com/documentation/spritekit/skviewdelegate

If I am understanding this correctly, then the only thing I need to look out for outside of this is ensuring that when returning from game, that the view.isPaused does not unpause my scene at the same exact time (ughhh why do you do this to me Apple) to allow for 1 render loop to occur.

Of course, the downside with this method, is any pause screen I create will have to be outside of this scene since rendering is disabled.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44
  • Any chance you found a solution that doesn’t stop rendering? – Mugs Jun 15 '20 at 02:55
  • @Mugs already said it, you need to handle it outside of the scene. If you create a node inside the scene, you can treat that node as your scene, and then just swap out “self” for that node. – Knight0fDragon Jun 15 '20 at 03:02
  • Ah sorry, missed that. Thanks for the help :) – Mugs Jun 17 '20 at 01:19