1

有没有办法使用 Swift 在 SpriteKit 中池/缓存 SKReferenceNodes?

我正在使用 xCodes 视觉关卡编辑器创建游戏。我正在使用可视级别编辑器创建不同的 .sks 文件,而不是在需要时调用代码。我在代码中调用它们是因为我正在使用它们来创建随机关卡或障碍物,因此我不需要将所有它们一次添加到场景中。

目前我正在这样做

我为 SKReferenceNodes 创建了一个令人信服的 init 方法来使用 URL 对其进行初始化。我这样做是因为有某种错误直接通过文件名调用 SKReferenceNodes ( https://forums.developer.apple.com/thread/44090 )。使用这样的扩展使代码更简洁。

 extension SKReferenceNode {

convenience init(roomName: String) {
    let path: String
    if let validPath = NSBundle.mainBundle().pathForResource(roomName, ofType: "sks") {
        path = validPath
    } else {
        path = NSBundle.mainBundle().pathForResource("RoomTemplate", ofType: "sks")! // use empty roomTemplate as backup so force unwrap
    }

    self.init(URL: NSURL(fileURLWithPath: path))
}

}

而不是在我的场景中,我可以创建它们并像这样添加它们(大约每 10 秒)

 let room = SKReferenceNode(roomName: "Room1") // will cause lag without GCD
 room.position = ...
 addChild(room)

这工作正常,但我在创建这些时遇到了一些滞后/口吃。所以我使用 GCD 将其减少到基本上没有口吃。它运作良好,但我想知道是否可以先预加载所有 .sks 文件。

我尝试使用数组来执行此操作,但我遇到了崩溃,它似乎不起作用(我还收到一条消息,已经添加了具有父节点的节点)。

我试图在应用启动时像这样预加载它们

 let allRooms = [SKReferenceNode]()

 for i in 0...3 {
     let room = SKReferenceNode(roomName: "Room\(i)")
     allRooms.append(room)
 }

而不是在我需要的时候使用数组。但是这不起作用,我在尝试使用这样的代码时崩溃了

 let room = allRooms[0]
 room.position = 
 addChild(room) // causes error/crash -> node already has parent

有没有人做过类似的事情?还有另一种方法可以池/缓存这些参考节点吗?我在这里错过了什么吗?

4

2 回答 2

1

说到SKReferenceNode预加载,我认为要遵循的策略是加载您的对象,找到它们的类型并使用Sprite-Kit中提供的官方预加载方法:

为避免此类错误,您应该创建单独的节点实例。

尝试这样做:

let room = allRooms[0]
room.position = ...
room.removeFromParent()
addChild(room)
于 2016-07-04T12:36:33.953 回答
1

我只是想通了,我只是一个白痴。

使用我想要的数组很好,导致崩溃的问题如下。

当游戏场景第一次加载时,我添加了 3 个房间,但是在使用阵列进行测试时,我一直添加同一个房间

let room = allRooms[0]

而不是使用随机化器。这显然意味着我多次添加相同的实例,因此崩溃了。

使用不会重复同一个房间的随机器,这不会发生。

此外,当我不再需要它时,我会确保将房间从场景中移除。我在房间中有一个节点(roomRemover),一旦它与玩家接触,它就会触发删除/创建新房间的方法。这将是 DidBeginContact 中的代码。

 guard let roomToRemove = secondBody?.node.parent?.parent?.parent?.parent else { return }
 // secondBody is the roomRemover node which is a child of the SKReferenceNode. 
 // If I want to remove the whole SKReferenceNode I need to add .parent 4 times. 
 // Not exactly sure why 4 times but it works

 for room in allRooms {
    if room == roomToRemove {
        room.removeFromParent()
    }
 }
 loadRandomRoom()

希望这可以帮助尝试做同样事情的人。

于 2016-07-04T13:54:20.317 回答