如何在多个精灵中添加碰撞


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return}
let location = touch.location(in: self)
lastTouchPosition = location

let bullet = SKSpriteNode(imageNamed: "bullet")
bullet.name = "bullet"
bullet.position = player.position
bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.contactTestBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.collisionBitMask = CollisionTypes.enemy.rawValue

bullet.size = CGSize(width: 40, height: 30)
bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width / 2)
addChild(bullet)
}

我用SKPhysicsBody给我的子弹添加了碰撞,它射击并碰撞我的敌人。然而,每次我触碰屏幕射击时,我的玩家都会被击倒,就像它有后坐力一样。如果我从子弹中移除SKPhysicsBody,一切都会正常运行,但是子弹会穿过敌人。

player.physicsBody?.categoryBitMask = CollisionTypes.player.rawValue
player.physicsBody?.contactTestBitMask = CollisionTypes.enemy.rawValue
player.physicsBody?.collisionBitMask = CollisionTypes.enemy.rawValue
player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue 
playerNode.physicsBody?.restitution = -1.0
playerNode.physicsBody?.friction = 0.0
playerNode.physicsBody?.angularDamping = 0.0
playerNode.physicsBody?.linearDamping = 0.5

你需要显示玩家的物理体和didBegin(contact:)的代码。从你所说的来看,似乎玩家正在与子弹碰撞,除非你采取特定的行动来阻止它,否则它将会发生。

子弹是根据玩家的位置创建的,所以他们试图占据相同的空间。如果你没有关闭玩家与子弹之间的碰撞,那么玩家就会与子弹发生碰撞并被"推开"。子弹不受影响,因为你已经将子弹的collisionBitMask设置为只针对敌人。

要关闭播放器和子弹之间的碰撞,而不影响玩家可能碰撞的其他任何东西,你可以使用:

player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue  

编辑:(你是对的-didBegin不需要碰撞)

我认为你在为子弹定义physicsBody时有一个问题:

bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.contactTestBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.collisionBitMask = CollisionTypes.enemy.rawValue
bullet.size = CGSize(width: 40, height: 30)
bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width / 2)

对于前3个引用的子弹的物理体,你使用一个可选的(子弹.物理体?),它说"如果物理体不是null,然后做这个…除非它是空的。您需要创建physicsBody的行(上面代码块的最后一行)作为实际创建physicsBody的第一行。目前你的categoryBitMask, collisionBitMask和contactTestBitMask没有为子弹设置。尽管这也会让子弹与玩家"碰撞"并弹开。

你是否为玩家做了类似的事情,因为听起来好像碰撞检测导致它被子弹反弹。

这可能会有帮助-如果你知道这些东西,我很抱歉。:如何在Swift, Sprite套件中检测碰撞

,这里有一个小的碰撞示例项目:https://stackoverflow.com/a/43605825/1430420

这两个答案都是几年前的事了,所以我希望它们仍然适用于最新版本的iOS, SpriteKit和Swift。

Edit2:

我也注意到了这个:

bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue

你试图给子弹一个敌人的类别。你是故意的吗?虽然子弹的physicsBody还没有设置,但是这行代码没有效果。

实际发生的情况是,当你创建子弹的实际physicsBody时,categoryBitMask的默认值被设置为全1。(https://developer.apple.com/documentation/spritekit/skphysicsbody/1519869-categorybitmask)意味着它与所有东西相撞。然后当你关闭玩家和子弹类别之间的碰撞时:

player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue 

玩家和子弹仍然会碰撞,因为你已经关闭了玩家和物理体之间的碰撞,只有子弹的类别,但子弹的物理体有一个类别,即玩家的碰撞bitmask是:

111111111111111111111111111111111101(假设敌人类别为2)

和bullet的bitMask是:

11111111111111111111111111111111111111111111111111,因为你没有在创建physicsBody后修改它。

当你将子弹的physicsBody的定义移动到bitMask设置之前,那么你就有了玩家的collisionBitMask仍然是:

111111111111111111111111111111111101(假设敌人类别为2)

但是bullet的collisionBitMask现在是:

00000000000000000000000000000100(假设你的敌人类别是4),因为你给了子弹的physicsBody类别BitMask敌人的类别,他们仍然碰撞,因为比特2在两个位掩码中都是1。

最新更新