如何实现SpriteKit中碰撞时仅被击中的单个Enemy节点消失
问题原因
你当前的代码只要检测到玩家与敌人的碰撞,就会遍历当前场景下所有名为Enemy的节点,删除所有符合位置条件的敌人,自然会出现所有敌人都消失的问题。实际上碰撞回调didBegin已经直接返回了发生碰撞的两个物理体,你不需要额外遍历所有敌人节点,直接删除被碰撞的敌人节点即可。
解决方法
修改你的碰撞检测代码如下:
func didBegin(_ contact: SKPhysicsContact) { var firstBody = SKPhysicsBody() var secondBody = SKPhysicsBody() // 区分玩家和碰撞对象 if contact.bodyA.node?.name == "Player" { firstBody = contact.bodyA secondBody = contact.bodyB } else { firstBody = contact.bodyB secondBody = contact.bodyA } // 检测碰撞双方是否为玩家+敌人,直接删除对应敌人 if firstBody.node?.name == "Player" && secondBody.node?.name == "Enemy" { // 直接移除被碰撞的单个敌人,不需要遍历 secondBody.node?.removeFromParent() } // 如果你需要单独清理超出边界的敌人,建议把这部分逻辑放到update方法里,不要放在碰撞回调中 /* self.enumerateChildNodes(withName: "Enemy") { (node:SKNode, nil) in if node.position.y < 550 || node.position.y > self.size.height + 550 { node.removeFromParent() } } */ }
补充说明
- 如果你用
categoryBitMask做碰撞分类更规范,可以把名称判断替换成位掩码判断,逻辑完全一致,只要确认玩家的位掩码是1、敌人的位掩码是2即可 - 原有清理超出边界敌人的逻辑不要放在碰撞回调里,建议放到场景的
update方法中按帧执行,避免碰撞时误执行全量遍历删除逻辑
内容的提问来源于stack exchange,提问作者user12137285
相关产品推荐
相关产品推荐

