Swift / SpriteKit - 任何池/缓存SKReferenceNodes的方法?

时间:2016-07-04 11:19:46

标签: swift caching sprite-kit preloading skreferencenode

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

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

目前我正在这样做

我为SKReferenceNodes创建了一个convince 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

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

2 个答案:

答案 0 :(得分:1)

谈到$ docker history node:latest IMAGE CREATED CREATED BY SIZE COMMENT a6b9ffdcf522 5 weeks ago /bin/sh -c #(nop) CMD ["node"] 0 B <missing> 5 weeks ago /bin/sh -c curl -SLO "https://nodejs.org/dist 41.51 MB <missing> 5 weeks ago /bin/sh -c #(nop) ENV NODE_VERSION=6.2.0 0 B <missing> 5 weeks ago /bin/sh -c #(nop) ENV NPM_CONFIG_LOGLEVEL=inf 0 B <missing> 5 weeks ago /bin/sh -c set -ex && for key in 9554F0 78.62 kB <missing> 5 weeks ago /bin/sh -c apt-get update && apt-get install 317.9 MB <missing> 5 weeks ago /bin/sh -c apt-get update && apt-get install 122.6 MB <missing> 5 weeks ago /bin/sh -c apt-get update && apt-get install 44.3 MB <missing> 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B <missing> 5 weeks ago /bin/sh -c #(nop) ADD file:5d8521419ad6cfb695 125.1 MB 预加载,我认为要遵循的政策是加载对象,找到它们的类型,并使用 Sprite-Kit 中提供的官方预加载方法:

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

尝试这样做:

.pt-flattened .pt-hcont{
    margin-left: 0 !important    
}

答案 1 :(得分: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()

希望这有助于某些人尝试这样做。