【问题标题】:SKSpriteNode showing non integer position when assigned an SKPhysicsBodySKSpriteNode 在分配 SKPhysicsBody 时显示非整数位置
【发布时间】:2017-06-19 19:52:53
【问题描述】:

我有一些非常简单的 Swift 代码,它将 SKSpriteNode 放置在屏幕上的位置 x:214, y:200。在更新方法中,我打印了所述 SKSpriteNode 的当前位置。如果我省略了所有 SKPhysicsBody 代码,那么我的 SKSpriteNode 的位置会在调试窗口中显示为 (214.0, 200.0),这与我预期的一样。但是,如果我在存在 SKPhysicsBody 代码的情况下运行程序,则第一次打印返回正确的 (214.0, 200.0),但随后的调用返回 (214.000015258789, 200.0)。

在我看来,这就像物理世界中的某些东西正在影响(尽管影响很小)SKSpriteNode 的位置。我一生无法理解的是那可能是什么。我的代码如下图所示,不多也不少。我想我已经禁用了所有可能对职位产生任何影响的东西。我只是希望我可能错过了一些愚蠢的事情。

这个问题可能看起来微不足道,因为这些值只是略微偏离,但是当我尝试在屏幕上平滑移动精灵时(每次更新时增加它的 x 位置 + 1),它偶尔会错过整个位置,从289.0 到 289.99,然后是 291.0。

任何帮助将不胜感激。这对我来说就像一个错误,但由于我对 SpriteKit 的物理方面还很陌生,所以我想确定一下。

import SpriteKit

class GameScene: SKScene {

private var playerSprite   : SKSpriteNode!

override func didMoveToView(view: SKView) {
    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)//borderBody
    self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)

    playerSprite = SKSpriteNode(color: UIColor.yellowColor(), size: CGSize(width: 100, height: 100))
    playerSprite.position = CGPoint(x: 214, y: 200)

    playerSprite.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 100, height: 100))

    if let playerSpritePhysicsObject = playerSprite.physicsBody {
        playerSpritePhysicsObject.usesPreciseCollisionDetection = true
        playerSpritePhysicsObject.affectedByGravity = false
        playerSpritePhysicsObject.allowsRotation = false
        playerSpritePhysicsObject.dynamic = false
        playerSpritePhysicsObject.angularVelocity = 0.0
        playerSpritePhysicsObject.friction = 0.0
        playerSpritePhysicsObject.linearDamping = 0.0
        playerSpritePhysicsObject.angularDamping = 0.0
        playerSpritePhysicsObject.velocity = CGVectorMake(0, 0)
        playerSpritePhysicsObject.restitution = 0.0
    }
    self.addChild(playerSprite)
}

override func update(currentTime: NSTimeInterval) {
    print("playerSprite Position = \(playerSprite.position)")
}
}

这里是调试窗口输出:

playerSprite Position = (214.0, 200.0)
2017-06-19 20:39:47.682 PhysicsTest[9193:2340365] <SKMetalLayer: 0x14fe6e760>: calling -display has no effect.
playerSprite Position = (214.000015258789, 200.0)
playerSprite Position = (214.000030517578, 200.0)
playerSprite Position = (214.000030517578, 200.0)
playerSprite Position = (214.000030517578, 200.0)
playerSprite Position = (214.000030517578, 200.0)

【问题讨论】:

  • 找了几天,终于找到有类似问题的人了。不幸的是,他们似乎也没有找到解决办法。 stackoverflow.com/questions/34236737/…
  • 我还发现了这个forums.developer.apple.com/thread/27057,虽然与我的问题不完全相同,因为我的 SKSpriteNode 不在 SKNode 对象中。似乎表明这可能是 2 年前的一个持续错误。
  • 我在我的代码中添加了一个变通方法,它确实似乎可以解决问题。这很讨厌但很有效。我们可以假设问题出在物理引擎及其 SKSpriteNode 的位置上,您可以通过在 didFinishUpdate() 函数中再次设置精灵的位置来强制精灵到正确的位置。
  • 不要偏离调试日志所说的内容,它有时可能会出错。进行实际比较 print(position.x == 214)
  • 在第一个'2 print'之后,位置是不变的。我认为正在发生的事情是你放置你的精灵,分配位置,然后在update() 中打印它。然后游戏循环的物理函数运行,并且根据一些内部处理,在接下来的 2 次迭代中位置会稍微改变。然后,在随后的游戏循环中,位置不会改变。

标签: ios swift sprite-kit


【解决方案1】:

在为这个问题苦恼一段时间后,我想我可能找到了解决办法。这很讨厌,但可以解决问题。只需在 didSimulatePhysics() 函数完成后发生的 didFinishUpdate() 函数中重置 SKSpriteNode 的位置。

override func didFinishUpdate() {
    playerSprite.position.x = 214
}

经过进一步测试,我发现这不适用于 iOS 7.1。为了让它在旧设备上工作,您必须将代码放在 didSimulatePhysics() 函数中:

override func didSimulatePhysics() {
    playerSprite.position.x = 214
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多