【问题标题】:SpriteKit node going through wallSpriteKit 节点穿墙
【发布时间】:2020-05-14 03:40:55
【问题描述】:

我正在开发一个 Xcode Playground,但遇到了一些 SpriteKit 碰撞问题。

第一个盒子的质量为 1,第二个盒子的质量为 100000(例如,当后者为 100 时,一切正常)。碰撞是弹性的(restitution 设置为 1),完全没有摩擦或阻尼。

这是我的场景的代码(ColliderType 只是类别的enum):

class GameScene: SKScene {
    private var wall: SKSpriteNode!
    private var floor: SKSpriteNode!
    private var box1: SKSpriteNode!
    private var box2: SKSpriteNode!

    override func didMove(to view: SKView) {
        self.backgroundColor = .white

        wall = SKSpriteNode(color: SKColor.black, size: CGSize(width: 10, height: self.frame.height))
        wall.position = CGPoint(x: 100, y: self.frame.height/2)
        wall.physicsBody = SKPhysicsBody(rectangleOf: wall.frame.size)
        wall.physicsBody?.isDynamic = false

        floor = SKSpriteNode(color: SKColor.black, size: CGSize(width: self.frame.width, height: 10))
        floor.position = CGPoint(x: self.frame.width/2, y: 100)
        floor.physicsBody = SKPhysicsBody(rectangleOf: floor.frame.size)
        floor.physicsBody?.isDynamic = false

        box1 = SKSpriteNode(color: SKColor.black, size: CGSize(width: 100, height: 100))
        box1.position = CGPoint(x: 300, y: floor.position.y+box1.size.height/2)
        box1.physicsBody = SKPhysicsBody(circleOfRadius: box1.frame.size.width/2)

        box2 = SKSpriteNode(color: SKColor.black, size: CGSize(width: 100, height: 100))
        box2.position = CGPoint(x: 750, y: floor.position.y+box2.size.height/2)
        box2.physicsBody = SKPhysicsBody(circleOfRadius: box2.frame.size.width/2)

        self.addChild(wall)
        self.addChild(floor)
        self.addChild(box1)
        self.addChild(box2)

        box1.physicsBody?.allowsRotation = false
        box2.physicsBody?.allowsRotation = false

        box1.physicsBody?.restitution = 1
        box2.physicsBody?.restitution = 1

        box1.physicsBody?.mass = 1
        box2.physicsBody?.mass = 100000

        box1.physicsBody?.friction = 0
        box2.physicsBody?.friction = 0

        box1.physicsBody?.linearDamping = 0
        box2.physicsBody?.linearDamping = 0

        wall.physicsBody?.categoryBitMask = ColliderType.Wall.rawValue
        box1.physicsBody?.categoryBitMask = ColliderType.Box1.rawValue
        box2.physicsBody?.categoryBitMask = ColliderType.Box2.rawValue

        box1.physicsBody?.collisionBitMask = ColliderType.Wall.rawValue | ColliderType.Floor.rawValue | ColliderType.Box2.rawValue
        box2.physicsBody?.collisionBitMask = ColliderType.Floor.rawValue | ColliderType.Box1.rawValue

        box1.physicsBody?.contactTestBitMask = ColliderType.Box2.rawValue | ColliderType.Wall.rawValue

        box1.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
        box2.physicsBody?.velocity = CGVector(dx: -50, dy: 0)
    }
}

我尝试过的事情:

  • 在第一个框上设置usesPreciseCollisionDetection = true
  • 通过覆盖 update 方法自行更新位置并检查碰撞(它没有像 SpriteKit 的引擎那样优化,所以速度很慢)
  • 使第二个框变慢并将physicsWorld.speed设置为大于1的数字

【问题讨论】:

    标签: swift xcode sprite-kit playgrounds


    【解决方案1】:

    我认为总的来说,您可能期望过高。 SpriteKit 是一个游戏引擎,旨在为涉及正常物理类型的场景提供定性合理的行为。这不是一个高精度的物理模拟,当你把它推到一个必须做极端事情的区域时,它可能会失败。

    在这种情况下,您期望它在很短的时间和距离内模拟大量完美的弹性碰撞(模拟的每个动画帧的许多碰撞,因为重块将轻块捣碎成一个微小的间隙)。它将找到帧中的第一个碰撞,计算施加到块的脉冲,然后前进到下一帧,效果是大块愉快地混入小块所在的空间。在搜索 60 fps 时会错过所有后续的碰撞。

    【讨论】:

    • 非常感谢!我也认为问题出在 SpritKit 的局限性上……我想我会想点别的(这是针对 Swift 学生挑战赛的)
    • 我假设这是为了说明碰撞块以计算 pi 的东西。您可能能够分析性地计算框架内应该发生的事情,并且只需使用 SpriteKit 进行绘图/动画。祝你好运!
    • 我试过了,但是更新方法会开始让实时取景滞后很多......另外,很酷的部分是使用默认的物理引擎来真正展示用这个计算 Pi是可能的。我已经找到了可以做的其他事情:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多