Search code examples
objective-csprite-kitdispatch-async

Problems loading scene async with button animation


I was trying to implement an animated start button in my main menu. Because my scene takes a while to load, I want to bridge the waiting time with that button animation. Unfortunately the animation does not start. What is the problem with my code?

-(void)buttonAnimation{
    SKAction *HUDzoom = [SKAction scaleTo:3 duration:1];
    SKAction *HUDzoomOut = [SKAction scaleTo:1.0 duration:1];
    SKAction *HUDAnimation = [SKAction sequence:@[HUDzoom, HUDzoomOut]];

    [self.startButton runAction:[SKAction repeatActionForever:HUDAnimation]];
}

-(void)loadScene{
    SKScene *restart = [[Level_1 alloc] initWithSize:self.size];
    [self.view presentScene:restart];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];

    SKNode *node = [self nodeAtPoint:location];

    if ([node.name isEqualToString:@"startLevel1"]){

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                [self loadScene];
            dispatch_async(dispatch_get_main_queue(), ^{
                [self buttonAnimation];
            });
        });

    }
}

Solution

  • That's because you're loading the scene asynchronically, and only after that is done you start the button animation asynchronically:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        // loading the scene
        [self loadScene];
    
        // when scene has finished loading, animate the button asynchronically
        // (this makes no sense)
        dispatch_async(dispatch_get_main_queue(), ^{
            [self buttonAnimation];
        });
    });
    

    Instead you should start the animation, then load the scene asynchronically.

    [self buttonAnimation];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            [self loadScene];
    });
    

    The button is animated by Sprite Kit actions, while you can start the animation asynchronically it won't make the entire animation asynchronically. Instead you just need to ensure that any blocking methods like loadScene run asynchronically.