【问题标题】:Different durations for SKAction - skipping around after action completion?SKAction 的不同持续时间 - 动作完成后跳来跳去?
【发布时间】:2016-12-29 05:41:47
【问题描述】:

我在GameViewController的乒乓球比赛中有以下代码:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self)

        main.run(SKAction.moveTo(x: location.x,duration: 4), completion: {
           print( "COMPLETED TOUCH BEGAN")
        })
    }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self)

        main.run(SKAction.moveTo(x: location.x,duration: 1), completion: {
            print( "COMPLETED TOUCH MOVED")
        })
    }
}

由于某种原因,当touchesBegan的持续时间大于touchesMoved的持续时间时,我的玩家会先完成touchesMoved的动作(尽管touchesBegan必须先来),然后跳转到一个不同的 x 位置,然后以持续时间 4 移动以完成 touchesBegan。这几乎就像玩家到达touchesMoved 中指定的位置(这应该与touchesBegan 中的位置几乎完全相同),返回一个稍微任意的量,然后移动到touchesBegan 位置。它为什么会跳回来然后像这样移动是有原因的吗?

我的假设是,出于某种原因,touchesMoved 动作同时运行,当它们完成时,位置跳回到它在touchesBegan 中缓慢移动的位置并完成该动作直到完成 - 几乎就像有两个物体以不同的速度移动,较慢的物体在较快的物体完成后出现。这完全正确吗?如果有,为什么会这样?

编辑

我看到当我让桨移动到屏幕的一侧,然后点击屏幕的另一端并滑过去,它会移动到我释放的最终位置,然后跳转并移动到我第一次按下的地方。这几乎就像第一个动作在后台播放一样。奇怪的是,如果我按住手指(保持touchesMoved 方法被调用)直到touchesBegan 中的移动完成(所以这里是4 秒),它不会跳到屏幕的另一边!

总之,我有多个 SKAction 以不同的持续时间运行,根据我的观察,优先级高于添加到操作数组中的最新操作。但不是相互播放多个动作,而是对象跳转到屏幕上的不同位置以完成最终动作。

【问题讨论】:

  • 你想达到什么目的?您在很短的时间内创建了许多相互冲突的操作。
  • @nathan 我实际上和this tutorial 一起关注并认为他所做的事情是正常的。我对 SpriteKit 完全陌生。不管怎样,我现在很好奇到底发生了什么。

标签: swift


【解决方案1】:

如果您设置第二个SKAction 移动同一个节点,则第二个不会抵消第一个。相反,节点的位置是在每一帧之后基于所有SKActions 运行计算的。如果SKActions 具有相同的持续时间并同时运行,则最后运行的SKAction 将始终胜出。例如:

// Same duration, node finishes at 100
main.run(SKAction.moveTo(x: -100, duration: 2)) //first to run
main.run(SKAction.moveTo(x: 100, duration: 2))  //second to run

如果第一个SKAction的持续时间更长,但是,在第二个SKAction完成后,将仅根据第一个SKAction计算位置,例如:

//First SKAction's duration is longer, node finishes at -100
main.run(SKAction.moveTo(x: -100, duration: 3))
main.run(SKAction.moveTo(x: 100, duration: 2))

这就是您看到“跳跃”的原因。

SKAction documentation

一个节点可以同时运行多个动作,即使这些动作 在不同的时间被处决。场景跟踪多远 每个动作都来自完成并计算该动作的效果 节点上有。例如,如果您运行两个动作来移动 同一个节点,这两个动作都将更改应用于每一帧。如果搬家 动作方向相等且方向相反,节点将保持不变 静止的。

在您的代码中touchesMoved 可以被多次调用,并且每次它都会向节点添加另一个SKAction。我建议您在运行另一个 SKAction 之前删除主节点上的所有操作:

main.removeAllActions()

所以最后会是:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self)
        main.removeAllActions()
        main.run(SKAction.moveTo(x: location.x,duration: 4), completion: {
            print( "COMPLETED TOUCH BEGAN")
        })
    }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self)
        main.removeAllActions()
        main.run(SKAction.moveTo(x: location.x,duration: 1), completion: {
            print( "COMPLETED TOUCH MOVED")
        })
    }
}

【讨论】:

  • 谢谢克雷格!当我可以访问 Xcode 时,我会再次重读这篇文章,但我对你的意思有点困惑,尽管 Apple 的文档说我认为相反,但这些操作没有取消。如果动作相等但相反,文档说动作将取消。但你是说最后的skaction会胜出。你能澄清一下吗?再次感谢您的详细回答。
  • 啊抱歉,这有点令人困惑 - 似乎 moveTomoveBy 工作方式不同,文档似乎指的是 moveBy。假设一个 moveBy 指定 x 移动为 100,另一个指定 x 移动为 -100 - 因为 100 减去 100 等于 0,所以这两个调用将相互抵消。 (假设他们的缓动是相同的)
  • 感谢您的澄清!所以在我的跳跃中,touchesBegan 是第一个并在后台的“幻象”上运行,而 touchesMoved 动作的运行时间较短?然后一旦 touchesMoved 动作结束,它会跳转到幻像对象的位置?我对它为什么以这种方式运行以及为什么 moveTo 命令以这种方式运行感到有些困惑。
  • 我不认为这是一个“幻像”,而是在渲染之前立即被另一个 SKAction 覆盖。 moveTo "从当前位置动画到新位置。"为了说明假设一个假设:节点位于 x=0,我们设置了两个 moveTo SKActions,都具有线性缓动,持续时间正好为 10 帧 - SKAction 1 moveTo x=100,SKAction 2 moveTo x=- 100。所以在第 1 帧中,它将执行以下操作:SKAction 1, moveTo (0 + (100/10)) = 10。但现在对于SKAction 2, moveTo (0 + (-100/10)) = -10 .现在在 -10 处渲染节点。
  • 确实有道理。但是对于不同的持续时间,当较短的持续时间结束时,它不会从当前位置移动。它似乎会跳到一个物体在背景中移动的位置。例如,假设 SKAction 1 是 10 帧,SKAction 2 是 5 帧。前五帧它将移动到 -50,然后我相信它会跳到 50 并再移动 50 帧以达到 100。根据我的理解,这是非常奇怪的行为,并且与它的动画想法不符当前位置。
猜你喜欢
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多