Runaction on Sknode Does Not Complete

SKAction runAction does not execute completion block

From the SKAction Reference:

An SKAction object is an action that is executed by a node in the
scene (SKScene)...When the scene processes its nodes, actions associated with those
nodes are evaluated.

In other words, the actions for a node is run if and only if that node is in the scene. By calling removeFromParent, you remove the node from the scene, the runBlock action is never called (since the node is no longer in the scene), and thus the sequence is never finished. Since the sequence doesn't finish, the completion block doesn't get called.

I would suggest moving the removeFromParent call to the completion block for safety's sake. Something like this feels safer:

for position in listOfPositions {

let theSprite: SKSpriteNode = theGrid[position]

/// the SKSpriteNode referenced by theSprite :
/// - belongs to an array of SKSpriteNode: theGrid
/// - belongs to a SKNode: theGameLayer
///
/// In other words this SKSpriteNode is referenced twice
///

let theActions = SKAction.sequence([
/// Some actions here
/// ...

/// Remove theSprite from the Grid
/// - position is an instance of a structure of my own
/// - theGrid is accessed via a subscript
///
SKAction.runBlock({self.theGrid[position] = nil})
])

theSprite.runAction(theActions) {
/// remove theSprite from it's parent
/// Might need to weakly reference self here
theSprite.removeFromParent(),
NSLog("Deleted")
}
}

TL;DR
The sequence doesn't complete, so the completion block for sequence doesn't get called.

Code inside SKAction run action not executing

Actions will not fire for a node until it is placed on the scene, you have a chicken and egg dilemma going on here. You want to add the node (egg) to the scene (chicken) after the node (egg) exists in the world (chicken gives birth to the same egg). You need to have somethings else place the node on the scene, then the node will be able to run the actions.

Place your start action on your scene, and not your node, and it should start running

SKAction not running on SKSpriteNode

myNode is a computed property. self.addChild(myNode) adds a node, but there is no myNode stored property.

myNode.run First computes a new node without adding it to the scene. Then it calls the run the action on it. but since it's a different node that is not on the scene, it will never run.

Change your myNode defintion to:

var myNode : SKShapeNode!

and in didMove(to view: add:

myNode = SKShapeNode(rectOf: snake.componentSize)
myNode.position = snake.head
myNode.fillColor = .red

Run action only on parent sknode

SpriteKit does not work this way. If your children should not be affected by the parent's movement, perhaps you should reconsider making them children.

However, there is a fun workaround: run an action on the children that counteracts the parent's movement. For example, if you run an action on the parent that moves to the left, run an action on all the children that moves them to the right simultaneously.

SKNode's action run completion block does not get called

Can I answer my own question? I guess I can? Here goes:

I finally solved this. It turns out that the WKInterfaceScene in WatchKit has ALSO an isPaused property that you need to turn false sometimes. So now in willActivate of my InterfaceController I will also check that and turn it false if it is true. Since I made this change, I haven't seen a single hiccup, freeze or anything weird anymore.

Case closed, I guess. I leave this here for future generations who might face this issue.

iOS SpriteKit SKAction completion call not working/creating odd results

It does not seem like you understand how runAction is executed.

Using

    [node runAction:moveUp completion:^{
NSLog(@"RUNNING MOVE DOWN");
[node setHidden: NO];
[node runAction: moveDown];
}];

will not just define a completion to be done at the end of the action, but it runs the action and then calls the completion, so the very first [node runAction:moveUp] needs to be removed.

Secondly, two runAction calls that are made in one function/block will be called simultaneously, and since you call [node runAction: moveUp], [node runAction:moveUp completion:] , and [node runAction:moveDown completion:] all in the same block, they will all be executed simultaneously.

This is the code you are looking for:

SKAction *moveUp = [SKAction moveTo: shipIntroSpot1 duration:3.0];
SKAction *moveDown = [SKAction moveTo:shipSpot1 duration:ship1MovementSpeed];

[self enumerateChildNodesWithName:@"ship1" usingBlock:^(SKNode *node, BOOL *stop) {
NSLog(@"RUNNING MOVE UP");

[node runAction:moveUp completion:^{
NSLog(@"RUNNING MOVE DOWN");
[node setHidden: NO];
[node runAction:moveDown completion:^{

NSLog(@"STARTING MOVEMENT");
}];
}];


Related Topics



Leave a reply



Submit