以编程方式添加 SKReferenceNode
Add SKReferenceNode programmatically
我的 2d 关卡很长,所以我将它分成了更多的 .sks 文件。我有 "GameScene",我可以通过拖放将它们加入到场景编辑器中。它创建 SKReferenceNodes。我已经成功地做到了。但是我想在代码中需要时延迟加载这些部分(据说这是一种很好的做法)。我在这方面失败了。
这是代码的特定部分:
if let nextPart = SKReferenceNode(fileNamed: "Scene2_city2") {
if self.childNodeWithName("Scene2_city2") == nil {
self.addChild(nextPart)
}
}
"Scene2_city2"是.sks文件的名称,也是文件中场景的名称。
运行 我得到错误的代码:
*** Terminating app due to uncaught exception 'Cant add body, already exists in a world', reason: 'Cant add body type: representedObject:[ name:'Scene2_city2' frame:{{-0, -0}, {1024, 768}} anchor:{0, 0}], already exists in a world'
这很奇怪,因为我在添加之前先检查它。
问题:我应该如何以编程方式将 SKReferenceNode 添加到 SKScene 中?
编辑:这里是 bitbucket 上的 simple example project。点击添加参考场景
您已检查节点是否在场景的层次结构中。此错误与物理世界有关,与场景中已添加节点无关。
就我个人而言,我无法使用 SKReferenceNode 重现您所说的内容,但这可能是因为我不完全了解您当前的设置。
如果两个节点指向同一个 SKPhysicsBody
实例,就会发生此错误,如下所示:
override func didMoveToView(view: SKView) {
let sprite = SKSpriteNode(color: .purpleColor(), size: CGSize(width: 20, height: 20))
let sprite2 = SKSpriteNode(color: .purpleColor(), size: CGSize(width: 20, height: 20))
sprite.position = CGPoint(x:frame.midX, y:frame.midY)
sprite2.position = CGPoint(x:frame.midX, y:frame.midY + 100)
let sharedPhysicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: -10, height: -10))
sprite.physicsBody = sharedPhysicsBody
sprite2.physicsBody = sharedPhysicsBody
addChild(sprite)
addChild(sprite2)
}
此代码将因您当前遇到的错误而崩溃。因此,检查您是否在某处或类似的地方重新使用相同的 SKPhysicsBody,您将解决这个问题。
我遇到了同样的问题。如果我使用 SKReferenceNode(fileNamed:) 从 scene.sks 文件中存在的精灵创建新精灵,我会收到错误
'Cant add body, already exists in a world'
这似乎与物理有关,并且在使用 addChild 将 object 添加到场景时发生。如果将 physics body 设置为 nil,错误就会消失。类似于:
let newBox = SKReferenceNode(fileNamed: "Box")
newBox?.physicsBody = nil
newBox?.position = location
addChild(newBox!)
有趣的是,即使将物理选项设置为 none,也会出现错误。上面的解决方案在这种情况下有效,但你失去了物理 body。
似乎对我有用的是创建一个 object 用作源 object,并使用 skNode.copy() 创建它的副本。
我找到了解决方法,事实证明使用 URL
方法创建 SKReferenceNode
时没有问题。
例如:
let path = NSBundle.mainBundle().pathForResource("SpaceShip", ofType: "sks")
let spaceShip = SKReferenceNode (URL: NSURL (fileURLWithPath: path!))
addChild(spaceShip)
我做了一些挖掘,它出现在 7.3.1 和 7.2.1 中,当创建一个 SKReferenceNode
使用 fileNamed
它现在 returns 一个可选的。展开后,您会得到 SKScene
如果您尝试将其作为子项添加到现有场景中,这当然会抛出错误。
添加了一个快速的 7.3 测试项目https://github.com/cocojoe/SKReferenceNodeIssue/tree/workaround
请注意,您在 Apple 论坛上引用了我的 post。我大约一个月前填写了一份错误报告,根据以往的经验,这些可能需要一段时间才能查看。
我发现了另一种解决方法,它不会强制您将 physicsBody 设置为 nil。
在我的例子中,我用 SKScene 替换了 SKReferenceNode。
我首先确保在我的 .sks 场景中,所有 SKSpriteNode 都是一个主节点的子节点。它不一定是直接的 link,您仍然可以尊重场景的层次结构,但重要的是在 "hierarchy tree" 的末尾它们被 linked 到一个节点,在我的例子中是背景,但它也可以是一个空节点。
然后在我的 GameScene 文件中编写了以下代码:
class GameScene: SKScene {
var mainNode: SKNode? = nil
override func didMove(to view: SKView) {
var mySksScene = SKScene(fileNamed: "Caribbeans")
mainNode = upperBackground?.childNode(withName: "backgroundCaribbean")
mainNode?.removeFromParent()
mySksScene = nil
addChild(mainNode)
}
}
我首先声明了一个可选的 SKNode 变量。然后,在 didMove(:to:) 中,我将我的 .sks 文件加载到一个可选的 SKScene() 变量中。然后我将 SKNode 设置为主节点,该节点是所有其他节点的父节点(在我的例子中:backgroundCaribbean)。然后我从它的父场景中删除了我的 mainNode,然后将用于包含 .sks 场景的变量设置为 nil,然后才将我的 mainNode 添加为我的 GameScene 的子节点。
我的 2d 关卡很长,所以我将它分成了更多的 .sks 文件。我有 "GameScene",我可以通过拖放将它们加入到场景编辑器中。它创建 SKReferenceNodes。我已经成功地做到了。但是我想在代码中需要时延迟加载这些部分(据说这是一种很好的做法)。我在这方面失败了。
这是代码的特定部分:
if let nextPart = SKReferenceNode(fileNamed: "Scene2_city2") {
if self.childNodeWithName("Scene2_city2") == nil {
self.addChild(nextPart)
}
}
"Scene2_city2"是.sks文件的名称,也是文件中场景的名称。
运行 我得到错误的代码:
*** Terminating app due to uncaught exception 'Cant add body, already exists in a world', reason: 'Cant add body type: representedObject:[ name:'Scene2_city2' frame:{{-0, -0}, {1024, 768}} anchor:{0, 0}], already exists in a world'
这很奇怪,因为我在添加之前先检查它。
问题:我应该如何以编程方式将 SKReferenceNode 添加到 SKScene 中?
编辑:这里是 bitbucket 上的 simple example project。点击添加参考场景
您已检查节点是否在场景的层次结构中。此错误与物理世界有关,与场景中已添加节点无关。
就我个人而言,我无法使用 SKReferenceNode 重现您所说的内容,但这可能是因为我不完全了解您当前的设置。
如果两个节点指向同一个 SKPhysicsBody
实例,就会发生此错误,如下所示:
override func didMoveToView(view: SKView) {
let sprite = SKSpriteNode(color: .purpleColor(), size: CGSize(width: 20, height: 20))
let sprite2 = SKSpriteNode(color: .purpleColor(), size: CGSize(width: 20, height: 20))
sprite.position = CGPoint(x:frame.midX, y:frame.midY)
sprite2.position = CGPoint(x:frame.midX, y:frame.midY + 100)
let sharedPhysicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: -10, height: -10))
sprite.physicsBody = sharedPhysicsBody
sprite2.physicsBody = sharedPhysicsBody
addChild(sprite)
addChild(sprite2)
}
此代码将因您当前遇到的错误而崩溃。因此,检查您是否在某处或类似的地方重新使用相同的 SKPhysicsBody,您将解决这个问题。
我遇到了同样的问题。如果我使用 SKReferenceNode(fileNamed:) 从 scene.sks 文件中存在的精灵创建新精灵,我会收到错误
'Cant add body, already exists in a world'
这似乎与物理有关,并且在使用 addChild 将 object 添加到场景时发生。如果将 physics body 设置为 nil,错误就会消失。类似于:
let newBox = SKReferenceNode(fileNamed: "Box")
newBox?.physicsBody = nil
newBox?.position = location
addChild(newBox!)
有趣的是,即使将物理选项设置为 none,也会出现错误。上面的解决方案在这种情况下有效,但你失去了物理 body。
似乎对我有用的是创建一个 object 用作源 object,并使用 skNode.copy() 创建它的副本。
我找到了解决方法,事实证明使用 URL
方法创建 SKReferenceNode
时没有问题。
例如:
let path = NSBundle.mainBundle().pathForResource("SpaceShip", ofType: "sks")
let spaceShip = SKReferenceNode (URL: NSURL (fileURLWithPath: path!))
addChild(spaceShip)
我做了一些挖掘,它出现在 7.3.1 和 7.2.1 中,当创建一个 SKReferenceNode
使用 fileNamed
它现在 returns 一个可选的。展开后,您会得到 SKScene
如果您尝试将其作为子项添加到现有场景中,这当然会抛出错误。
添加了一个快速的 7.3 测试项目https://github.com/cocojoe/SKReferenceNodeIssue/tree/workaround
请注意,您在 Apple 论坛上引用了我的 post。我大约一个月前填写了一份错误报告,根据以往的经验,这些可能需要一段时间才能查看。
我发现了另一种解决方法,它不会强制您将 physicsBody 设置为 nil。
在我的例子中,我用 SKScene 替换了 SKReferenceNode。
我首先确保在我的 .sks 场景中,所有 SKSpriteNode 都是一个主节点的子节点。它不一定是直接的 link,您仍然可以尊重场景的层次结构,但重要的是在 "hierarchy tree" 的末尾它们被 linked 到一个节点,在我的例子中是背景,但它也可以是一个空节点。
然后在我的 GameScene 文件中编写了以下代码:
class GameScene: SKScene {
var mainNode: SKNode? = nil
override func didMove(to view: SKView) {
var mySksScene = SKScene(fileNamed: "Caribbeans")
mainNode = upperBackground?.childNode(withName: "backgroundCaribbean")
mainNode?.removeFromParent()
mySksScene = nil
addChild(mainNode)
}
}
我首先声明了一个可选的 SKNode 变量。然后,在 didMove(:to:) 中,我将我的 .sks 文件加载到一个可选的 SKScene() 变量中。然后我将 SKNode 设置为主节点,该节点是所有其他节点的父节点(在我的例子中:backgroundCaribbean)。然后我从它的父场景中删除了我的 mainNode,然后将用于包含 .sks 场景的变量设置为 nil,然后才将我的 mainNode 添加为我的 GameScene 的子节点。