SpriteKit节点穿过墙壁

问题描述 投票:1回答:1

我正在做一个Xcode Playground,我在SpriteKit碰撞方面遇到了一些问题。

GIF of Playground

第一个盒子的质量为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 在第一个盒子上
  • 我自己通过覆盖更新方法来更新位置和检查碰撞(它不像SpriteKit的引擎那样优化,所以很慢)。
  • 让第二个箱子慢一点,并设置 physicsWorld.speed 大于1的数字
swift xcode sprite-kit playgrounds
1个回答
0
投票

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

在这种情况下,你希望它在很小的时间和距离内模拟出大量完美的弹性碰撞(每个动画帧的模拟中,重块将轻块捣毁成一个微小的缝隙时,会发生许多碰撞)。 它要找到这一帧中的第一次碰撞,计算出应用于块体的脉冲,然后推进到下一帧,效果是大块体愉快地捣进小块体所在的空间。 为了寻求60帧的速度,所有后续的碰撞都会被错过。

© www.soinside.com 2019 - 2024. All rights reserved.