問題
ノード階層がエンコードされると、アプリケーションの状態の保存や「ゲームの保存」中によくSKAction
あることですが、コード ブロックをエンコードできないため、コード ブロックでアクションを実行しているノードは特別に処理する必要があります。
例 1: アニメーション後の遅延コールバック
ここで、オークが殺されました。アニメーション化されてフェードアウトし、ノード階層から削除されます。
SKAction *fadeAction = [SKAction fadeOutWithDuration:3.0];
SKAction *removeAction = [SKAction removeFromParent];
[orcNode runAction:[SKAction sequence:@[ fadeAction, removeAction ]]];
orc ノードがエンコードされてからデコードされた場合、アニメーションは適切に復元され、期待どおりに完了します。
ただし、この例は、フェード後に実行されるコード ブロックを使用するように変更されています。おそらく、オークが(最終的に)死んだら、コードはゲームの状態をクリーンアップします。
SKAction *fadeAction = [SKAction fadeOutWithDuration:3.0];
SKAction *removeAction = [SKAction removeFromParent];
SKAction *cleanupAction = [SKAction runBlock:^{
[self orcDidFinishDying:orcNode];
}];
[orcNode runAction:[SKAction sequence:@[ fadeAction, removeAction, cleanupAction ]]];
残念ながら、コード ブロックはエンコードされません。アプリケーションの状態の保存 (またはゲームの保存) 中に、このシーケンスが実行されている場合、警告が発行されます。
SKAction: 実行ブロック アクションを正しくエンコードできません。Objective-C ブロックは NSCoding をサポートしていません。
デコード後、オークはフェードして親から削除されますが、クリーンアップ メソッドorcDidFinishDying:
は呼び出されません。
この制限を回避する最善の方法は何ですか?
例 2: トゥイーン
SKAction
customActionWithDuration:actionBlock:
トゥイーンに美しくフィットするようです。この種の定型コードは次のとおりです。
SKAction *slideInAction = [SKAction customActionWithDuration:2.0 actionBlock:^(SKNode *node, CGFloat elapsedTime){
CGFloat normalTime = (CGFloat)(elapsedTime / 2.0);
CGFloat normalValue = BackStandardEaseInOut(normalTime);
node.position = CGPointMake(node.position.x, slideStartPositionY * (1.0f - normalValue) + slideFinalPositionY * normalValue);
}];
残念ながらcustomActionWithDuration:actionBlock:
エンコードできません。アニメーション中にゲームが保存されると、ゲームのロード時に正しく復元されません。
繰り返しますが、この制限を回避する最善の方法は何ですか?
不完全なソリューション
ここに私が検討したが気に入らない解決策があります。(そうは言っても、これらのいずれかをうまく擁護する回答を読みたいです。)
不完全な解決策:アニメーションでは
performSelector:onTarget:
なく使用します。runBlock:
呼び出されたセレクターに引数を渡すことができないため、この解決策は不完全です。呼び出しのコンテキストは、ターゲットとセレクターの名前によってのみ表現できます。良くない。不完全な解決策: エンコード中に、
SKAction
関連するノードからシーケンスを削除し、シーケンスが完了したかのようにプログラムの状態を進めます。alpha
最初の例では、ノードをすぐに に設定し0.0
、orc ノードを親から削除して、 を呼び出すことを意味しますorcDidFinishDying:
。これは、少なくとも 2 つの理由から残念な解決策です。1) エンコード中に特別な処理コードが必要です。2) 視覚的には、ノードはアニメーションを終了する機会を得られません。SKAction
不完全な解決策: エンコード中に、関連するノードからコード ブロックを削除し、デコード中にそれらを再作成します。これは自明ではありません。不完全な解決策:
SKAction
特に遅延の後では、コード ブロックを使用しないでください。アプリの良好な状態を復元するために、アニメーションの完了に依存しないでください。(将来のイベントをエンコード可能な方法でスケジュールする必要がある場合は、コード ブロックを使用せずに独自のイベント キューを作成してください。) この解決策は不完全です。なぜならrunBlock
、 とcustomActionWithDuration:actionBlock:
は非常に便利であり、恥ずべきことです (そして、初心者にとっては繰り返し起こる罠です)。 )それらを悪と見なす。