Swift SpriteKit - “尝试添加一个已经有父节点的 SKNode”,同时添加关节
Posted
技术标签:
【中文标题】Swift SpriteKit - “尝试添加一个已经有父节点的 SKNode”,同时添加关节【英文标题】:Swift SpriteKit - "Attempted to add a SKNode which already has a parent" while adding Joint 【发布时间】:2016-04-01 00:19:49 【问题描述】:我在躺着并从背部手术中恢复时正在学习 SpriteKit。感谢您帮助我了解为什么会出现此错误。
我有一个精灵“zombie1”,我可以通过计时器调用它,它会一遍又一遍地生成,然后毫无问题地在屏幕上移动,直到我尝试添加 riotShield Sprite。一旦我这样做了,它会在第二次调用 func 并且第一个 riotShield 已经存在时崩溃:
func addZ1ArmoredShield()
zombie1Mask = SKSpriteNode(texture: zombie1Texture)
var TextureAtlas = SKTextureAtlas()
var TextureArray = [SKTexture]()
TextureAtlas = SKTextureAtlas(named: "ZombieArmored")
for i in 1...TextureAtlas.textureNames.count
let Name = "armoredZombie_\(i)"
TextureArray.append(SKTexture(imageNamed: Name))
zombie1 = SKSpriteNode(imageNamed: TextureAtlas.textureNames[0] as String)
zombie1.name = "monster"
zombie1.position = CGPointMake(globalVariables.skScene.frame.size.width + 50, CGFloat(randomStartPosition()))
let moveZombie1 = SKAction.moveToX(0, duration: spawnSpeed1() )
let removeZombie1 = SKAction.removeFromParent()
let moveAndRemoveZombie1 = SKAction.sequence([moveZombie1, removeZombie1])
zombie1.runAction(moveAndRemoveZombie1) zombie1.runAction(SKAction.repeatActionForever(SKAction.animateWithTextures(TextureArray, timePerFrame: 0.1)))
zombie1.physicsBody = SKPhysicsBody(texture: zombie1MaskTexture, size: zombie1Mask.size)
zombie1.physicsBody!.dynamic = true
zombie1.physicsBody!.affectedByGravity = false
zombie1.physicsBody!.charge = 50
zombie1.physicsBody!.usesPreciseCollisionDetection = true
zombie1.physicsBody!.categoryBitMask = ColliderType.monster2HPContact.rawValue
zombie1.physicsBody!.contactTestBitMask = ColliderType.bulletContact.rawValue|ColliderType.bottemEdge.rawValue|ColliderType.topEdge.rawValue|ColliderType.monster2HPContact.rawValue|ColliderType.heroTop.rawValue
zombie1.physicsBody!.collisionBitMask = ColliderType.bottemEdge.rawValue|ColliderType.topEdge.rawValue
zombie1.physicsBody!.fieldBitMask = ColliderType.monsterContact.rawValue
zombie1.physicsBody!.mass = 2
zombie1.physicsBody!.allowsRotation = false
riotShield.name = "RiotShield"
riotShield.color = SKColor.blackColor()
riotShield.size = CGSizeMake(2, 25)
riotShield.position = CGPoint(x: (zombie1.position.x + 80 ), y: (zombie1.position.y + 40 ))
riotShield.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, 25))
riotShield.physicsBody!.categoryBitMask = ColliderType.riotShieldContact.rawValue
riotShield.physicsBody!.contactTestBitMask = ColliderType.bulletContact.rawValue
riotShield.physicsBody!.dynamic = true
riotShield.physicsBody!.affectedByGravity = false
riotShield.physicsBody!.usesPreciseCollisionDetection = true
let riotShieldJoint = SKPhysicsJointFixed.jointWithBodyA(zombie1.physicsBody!, bodyB: riotShield.physicsBody!, anchor: CGPoint(x: (zombie1.position.x + 10 ), y: zombie1.position.y + 10 ))
globalVariables.currentScene.addChild(zombie1)
globalVariables.currentScene.addChild(riotShield)
globalVariables.currentScene.physicsWorld.addJoint(riotShieldJoint)
//end function
我不明白为什么我的zombie1 创建了一个 SKSpritenode 的实例,但我的 riotShield 被视为试图添加到同一个父节点的单个精灵。我已经阅读了大量有关此错误的帖子,并且我想我了解原因(riotShield 未作为实例添加)。我只是不明白这两个精灵之间的区别,以及当我以基本相同的方式添加它们时它们的行为不同。
感谢您的宝贵时间和您可能提供的任何帮助。
【问题讨论】:
同一节点只能有一个父节点。如果您尝试将其添加到另一个父级,则会发生此崩溃......而且globalVariables
的东西看起来很阴暗:)
谢谢,globalVariable 只是指向当前场景,所以该函数总是将精灵添加到活动的“关卡”场景中。关于单亲,这确实有道理,我只是不太明白zombie1和riotShield在这方面的区别。我可以毫无问题地添加zombie1 一百次,但是一旦添加了第二个riotShield,它就会崩溃。你知道为什么 riotShield 被应用到与第一个实例相同的父级上,但zombie1 没有吗? (对不起,如果这是一个愚蠢的问题。
所以场景总是存在的对吧?如果是这样,添加的精灵永远不会被删除,并且当您尝试再次添加它们时,您会崩溃。不确定您当前的设置(以及为什么要这样做),但保留这样的场景可能不是一个好主意。你有多少场景?
我有 6 个场景,它们根据“僵尸”的速度类型而有所不同。在我尝试了解关节之前,我对父问题没有任何问题,这是我第一次尝试像这样在 1 个函数中添加 2 个精灵。 (感谢您的浏览和反馈)
【参考方案1】:
基于单亲问题并查看我添加“riotShield”节点的方式,我发现这是我使用 SKSpritenode 作为 shapenode 的方式,这显然改变了它的行为。
通过将 riotShield 添加为如下图片,一切正常。
riotShield.name = "RiotShield"
riotShield = SKSpriteNode(imageNamed: "riotShield1")
riotShield.position = CGPoint(x: (zombie1.position.x + 80 ), y: (zombie1.position.y + 40 ))
riotShield.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, 25))
riotShield.physicsBody!.categoryBitMask = ColliderType.riotShieldContact.rawValue
riotShield.physicsBody!.contactTestBitMask = ColliderType.bulletContact.rawValue
riotShield.physicsBody!.dynamic = true
riotShield.physicsBody!.affectedByGravity = false
riotShield.physicsBody!.usesPreciseCollisionDetection = true
感谢所有发布其他问题并回复我的人。
【讨论】:
哦,我现在看到了问题。这不是您使用 SKSpriteNode 的方式(如果它是 SKSpriteNode,则不能像 SKShapeNode 那样使用它)。这是因为 riotShield 是场景的属性,当您多次调用此方法时,游戏会崩溃。现在它可以工作了,因为您每次都在重新初始化riotShield
,使用这一行 riotShield = SKSpriteNode(imageNamed: "riotShield1")。在您之前的代码中,您一直在重复使用同一个精灵,它已经有一个父对象,因此出现了错误。以上是关于Swift SpriteKit - “尝试添加一个已经有父节点的 SKNode”,同时添加关节的主要内容,如果未能解决你的问题,请参考以下文章
将 SKSpriteNode 移动 Y - Swift 2 + SpriteKit
SpriteKit 设备方向改变导致 SKLabelNode 变形 Swift