SKPhysicsContact接触检测后敌人未移除及玩家出界问题求助
问题1:敌人无法被删除的根因
你的碰撞检测代码存在明确逻辑错误:
- 你在碰撞逻辑第一步就修改了子弹的
categoryBitMask,虽然这不是本次问题的直接诱因,但会导致后续的碰撞类型判断不可靠,正确的做法是先将两个碰撞体的类型存入临时变量,再做逻辑判断 - 核心逻辑写反:当你检测到
bodyB是敌人类型时,你执行的是删除bodyA对应的节点(也就是子弹),敌人节点完全没有被执行移除操作;反过来如果检测到bodyA是敌人类型,你删除的是bodyB对应的节点,同样不会处理敌人本身。这就是子弹被删除但敌人保留的直接原因。
问题2:玩家超出屏幕边界的原因
你之前的代码会在碰撞判定时随意将碰撞体的physicsBody置为nil,如果某次碰撞误把玩家的物理体置空,玩家就失去了和屏幕边界物理体的碰撞约束,自然会超出屏幕。你删除置空physicsBody的代码解决了玩家的问题,但原代码的核心缺陷是没有先明确碰撞双方的类型就执行通用的节点属性修改,确实有概率误操作敌人或者其他节点的属性,留下后续隐患。
修复方案
如果你的项目不需要复用子弹/敌人节点,直接调用removeFromParent()就足够了,节点移除后对应的物理体、动作都会被自动回收,不需要手动置空属性。如果你的项目用了节点池做对象复用,可以在移除节点前先将categoryBitMask和collisionBitMask置为0,避免复用前触发多余的碰撞。
修复后的参考代码:
func didBegin(_ contact: SKPhysicsContact) { // 先提取两个碰撞体的类型存入临时变量,避免后续修改属性导致判断异常 let bodyACategory = contact.bodyA.categoryBitMask let bodyBCategory = contact.bodyB.categoryBitMask // 仅处理子弹和敌人的碰撞组合 if (bodyACategory == bulletCategory && bodyBCategory == enemyCategory) { contact.bodyA.node?.removeFromParent() contact.bodyB.node?.removeFromParent() } else if (bodyACategory == enemyCategory && bodyBCategory == bulletCategory) { contact.bodyA.node?.removeFromParent() contact.bodyB.node?.removeFromParent() } }
内容的提问来源于stack exchange,提问作者nathandr
相关产品推荐
相关产品推荐

