首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift/SpriteKit -有什么方法可以池/缓存SKReferenceNodes?

Swift/SpriteKit -有什么方法可以池/缓存SKReferenceNodes?
EN

Stack Overflow用户
提问于 2016-07-04 11:19:45
回答 2查看 253关注 0票数 1

是否有一种使用Swift在SKReferenceNodes中池/缓存SpriteKit的方法?

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

此刻我正在这样做

我为SKReferenceNodes创建了一种使人信服的init方法,使其能够使用URL插入它们。我这样做是因为有某种错误直接通过文件名(https://forums.developer.apple.com/thread/44090)调用https://forums.developer.apple.com/thread/44090。使用这样的扩展可以使代码更加简洁。

代码语言:javascript
复制
 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秒)。

代码语言:javascript
复制
 let room = SKReferenceNode(roomName: "Room1") // will cause lag without GCD
 room.position = ...
 addChild(room)

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

我尝试使用数组来完成这个任务,但是我遇到了崩溃,但它似乎不起作用(我还收到了一条消息,已经添加了具有父节点的节点)。

我试着像在应用启动时那样预加载它们

代码语言:javascript
复制
 let allRooms = [SKReferenceNode]()

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

也不要在我需要的时候使用数组。然而,这不起作用,当我试图使用这样的代码时,我会崩溃

代码语言:javascript
复制
 let room = allRooms[0]
 room.position = 
 addChild(room) // causes error/crash -> node already has parent

有人做过类似的事吗?还有其他方法可以池/缓存这些引用节点吗?我是不是漏掉了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-04 13:54:20

我刚想明白,我只是个白痴。

使用我想要的数组是很好的,造成崩溃的原因是以下问题。

当游戏场景第一次加载时,我增加了3个房间,但是当测试数组时,我一直在添加相同的空间。

代码语言:javascript
复制
let room = allRooms[0]

而不是使用随机变量。这显然意味着我要多次添加相同的实例,从而导致崩溃。

如果有一个随机变量,这不会重复同一个房间,这不会发生。

此外,当我不再需要的时候,我一定要把房间从现场移开。我在房间中有一个节点(roomRemover),一旦它与播放器接触,就会触发一种方法来删除/创建一个新的房间。这将是DidBeginContact中的代码。

代码语言:javascript
复制
 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()

希望这能帮助那些想做同样事情的人。

票数 1
EN

Stack Overflow用户

发布于 2016-07-04 12:36:33

说到SKReferenceNode预加载,我认为要遵循的策略是加载对象,找出它们是什么类型,并使用Sprite-Kit中可用的官方预加载方法。

为了避免这种错误,您应该创建节点的单独实例。

试着这样做:

代码语言:javascript
复制
let room = allRooms[0]
room.position = ...
room.removeFromParent()
addChild(room)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38183466

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档