SpriteKit:如何立即使用 removeAllActions 停止操作

Posted

技术标签:

【中文标题】SpriteKit:如何立即使用 removeAllActions 停止操作【英文标题】:SpriteKit: How to stop actions with removeAllActions immediately 【发布时间】:2016-05-22 08:50:53 【问题描述】:

根据文档,removeAllActions 会立即取消操作,但对象的状态至少会更新一个刻度。

我有一个简单的缩放动画,

let scaleUp = SKAction.scaleBy(2.0, duration: time)
sprite.runAction(scaleUp)

以及删除所有操作并重置比例的事件。该事件在 touchesBegan 周期内被调用,

sprite.removeAllActions()
sprite.setScale(1.0)

动画停止,但精灵的比例仍然错误。如果我再次调用相同的事件,则秤会正确重置。

这些行动的确切时间是什么?该文档似乎没有提到任何时间问题。否则,我希望有一个“onCancel”回调,可以传递给 runAction 并在删除它后调用,类似于“完成”。

编辑: 问题是我的一些代码试图在删除动作之前重置精灵的大小(我正在更新它的纹理,纵横比可能会改变,所以大小需要更新)

根据 Whirlwind 下面的回答复制案例。

class GameScene: SKScene 
let sprite = SKSpriteNode(color: .whiteColor(), size: CGSize(width: 123, height: 123))
override func didMoveToView(view: SKView) 
    sprite.alpha = 0.5
    sprite.position = CGPoint(x: 448, y: 223)
    addChild(sprite)

private func scaleTest() 
    let scaleUp = SKAction.scaleBy(2.0, duration: 0.5)
    let scaleDown = SKAction.scaleTo(1.0, duration: 3)
    sprite.runAction(SKAction.sequence([scaleUp, scaleDown]))

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
    if sprite.hasActions() 
        sprite.size = CGSize(width: 123, height: 123)
        sprite.removeAllActions()
        sprite.setScale(1.0)
     else 
        scaleTest()
    


修复:

        sprite.removeAllActions()
        sprite.setScale(1.0)
        sprite.size = CGSize(width: 123, height: 123)

【问题讨论】:

我注意到的另一件奇怪的事情是精灵最终可能小于 scale = 1,这根本没有意义,因为我总是按比例放大。我唯一能想到的是,因为我调用 scaleBy(2) 然后 scaleTo(1),如果在 setScale(1) 之间调用并且操作没有终止,则从 1 继续缩小“到 1”到更小的东西。 【参考方案1】:

我无法重现您所说的内容。对我来说,一切正常。看看这个例子(我没有改变场景的大小,所以默认是 1024x768):

import SpriteKit

class GameScene: SKScene 

    let sprite = SKSpriteNode(color: .whiteColor(), size: CGSize(width: 123, height: 123))


    override func didMoveToView(view: SKView) 

        sprite.alpha = 0.5

         let sprite1 = SKSpriteNode(color: .redColor(), size: CGSize(width: 123, height: 123))

        let scaleUp = SKAction.scaleBy(2.0, duration: 7)
        sprite.runAction(scaleUp)
        sprite.position = CGPoint(x: 448, y: 223)
        addChild(sprite)

        sprite1.position = sprite.position
        addChild(sprite1)
    


    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 


        sprite.removeAllActions()
        sprite.setScale(1.0)
    


注意点击屏幕时白色精灵是如何缩放到其原始大小的(至少在我的情况下)。

关于 SKActions 如何工作的一个值得一提的事实是,动作被排队并且总是在下一帧中处理。此外,您不能在未添加到场景中的节点上运行操作。关键是您发布的内容应该可以工作,如果它不工作,那么还有其他问题,但不是这部分代码。

【讨论】:

您可能希望在运行之前将 Sprite 添加到父级进行测试。 感谢您的测试。我试过了,确实我无法重现我的问题。我试图创建一个独立的测试,但我没有成功。我的精灵是 SKSpriteNode 的子类,它包含对另一个精灵的弱引用,它自己的孩子。那个孩子就是我正在制作动画的那个。在隔离时,它工作正常。缩放函数从 runBlock 调用自身进行迭代,这可能会弄乱时间,但我也尝试将其添加到您的测试中,但也无法重现:/ 我终于找到了问题所在。我班级的纹理设置器有一些逻辑来重新计算精灵大小,我在删除所有动作之前更新了纹理(因此可能会改变精灵大小)。我已经根据您的示例更新了问题的描述。谢谢! @endavid 欢迎您。很高兴听到你把它整理出来;)

以上是关于SpriteKit:如何立即使用 removeAllActions 停止操作的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit 加载新场景但精灵立即下降

PhysicsBody 使用 SpriteKit 和 Swift 为零

科尔多瓦/PhoneGap/离子:fileEntry.remove();不立即删除文件

BFTask 在后台绘制 SpriteKit 对象正在锁定主线程

更改 spritekit 中的节点颜色

无法使应用程序进入主菜单(Swift 4 SpriteKit)