Swift 4游戏开发报错:添加已有父节点的SKNode求助
Swift 4游戏循环生成地面与金币报错解决
我用Swift 4开发一款游戏,想要实现玩家下落时在不同高度随机生成带金币的地面的循环逻辑,但出现了报错:
Thread 1: "Attemped to add a SKNode which already has a parent: name:'(null)' texture:[ 'coin1' (359 x 357)] position:{865, 2030} scale:{1.00, 1.00} size:{100, 100} anchor:{0.5, 0.5} rotation:0.00"
问题原因
错误核心是:你试图添加一个已经有父节点的SKNode——也就是你在类顶部声明的全局coin对象。第一次调用makePlatform()时,这个coin被添加到场景成为子节点;第二次调用makePlatform()时,它还属于之前的父节点,再次执行addChild(coin)就会触发这个报错。
解决方案
每次生成平台时,创建新的金币实例,不要复用全局的coin对象。另外可以把金币挂载到平台节点下,方便后续统一移除管理。
修改后的代码示例
class GameScene: SKScene...{ // 只保留纹理引用,避免复用节点实例 let platformTexture = SKTexture(imageNamed: "ground") let coinTexture1 = SKTexture(imageNamed: "coin1") let coinTexture2 = SKTexture(imageNamed: "coin2") enum bitmasks: UInt32 { case player = 0b1 case platform = 0b10 case coin = 0b100 // 补充coin的位掩码值,原代码缺失 } override func didMove(to view: SKView) { ... makePlatform() } func makePlatform() { let platform = SKSpriteNode(texture: platformTexture) platform.position = CGPoint( x: GKRandomDistribution(lowestValue: 0, highestValue: 800).nextInt(), y: GKRandomDistribution(lowestValue: 1200, highestValue: 1225).nextInt() - Int(player.position.y - 1000) ) // 补充平台的物理位掩码设置 platform.physicsBody?.categoryBitMask = bitmasks.platform.rawValue // 每次创建新的金币节点 let coin = SKSpriteNode(texture: coinTexture1) coin.position = CGPoint(x: platform.position.x + 80, y: platform.position.y + 80) coin.zPosition = 6 coin.setScale(1) coin.physicsBody?.categoryBitMask = bitmasks.coin.rawValue // 把金币添加到平台下,移除平台时自动连带移除金币 platform.addChild(coin) addChild(platform) } func didBegin(_ contact: SKPhysicsContact) { // 修正碰撞判断逻辑,兼容contactA和contactB的顺序 let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask let targetMask = bitmasks.platform.rawValue | bitmasks.cameraLine.rawValue if contactMask == targetMask { // 确定平台节点 let platformNode = contact.bodyA.categoryBitMask == bitmasks.platform.rawValue ? contact.bodyA.node : contact.bodyB.node platformNode?.removeFromParent() makePlatform() } } }
额外注意点
- 原代码中
bitmasks枚举的coincase没有赋值,必须补充唯一的位掩码值,否则物理碰撞检测会失效。 - 碰撞判断要考虑
contactA和contactB的顺序问题,用掩码合并的方式可以避免漏判。 - 如果需要随机切换金币纹理,可以在创建金币时用随机数选择
coinTexture1或coinTexture2。
内容的提问来源于stack exchange,提问作者sweeping
相关产品推荐
相关产品推荐

