上次說到SpriteKit中有各種奇葩的東西。今天再講一個,這次的主角是GKGridGraph。
嚴格意義上講,這個類并不屬于SpriteKit,而是被包含在GameplayKit。不過SpriteKit開發(fā)經(jīng)常需要用到GameplayKit,反正要吐槽,干脆就一起吐了吧。
我做的游戲是一個塔防類游戲,需要計算路徑。而GKGridGraph用來描述二維世界中的連接。
在場景生成的時候,我需要創(chuàng)建GKGridGraph
graph = GKGridGraph(fromGridStartingAt: int2(0, 0), width: Int32(gridColumns), height: Int32(gridRows), diagonalsAllowed: false)
隨后,加載地圖中的障礙或者塔的時候,障礙或者塔所占的節(jié)點需要從GKGridGraph刪除,只有這樣敵人才可以找到正確的路徑。刪除節(jié)點的代碼如下:
func removeGraphNodes (nodes: [GKGridGraphNode]){
graph.removeNodes(nodes)
for node in nodes {
removedNodes.append(node)
}
}
那么每一關(guān),我需要重新構(gòu)建這個graph。很自然,應(yīng)該還是用上面的代碼來構(gòu)建:
graph = GKGridGraph(fromGridStartingAt: int2(0, 0), width: Int32(gridColumns), height: Int32(gridRows), diagonalsAllowed: false)
但是執(zhí)行的時候,第一次創(chuàng)建沒問題,再次創(chuàng)建的時候就會出現(xiàn)一個EXC_BAD_ACCESS的錯誤,然后程序就會奔潰。
我驚奇的發(fā)現(xiàn),居然還有這樣的事情:變量居然不能重新賦值!我驚奇的google了一下,發(fā)現(xiàn)這個奇葩的問題不少人都遇到了,比如:
http://stackoverflow.com/questions/34165108/exc-bad-access-when-reasigning-gkgridgraph
http://www.raywenderlich.com/forums/viewtopic.php?f=2&t=24412
有人說iOS SDK 9.2出這個問題,而9.0不會。
我沒有辦法試,因為我不想折騰裝9.0??戳艘恍﹦e人的游戲,有些人和我不同,他們每一關(guān)都重新構(gòu)建一個SKScene,所以也不存在我的這個問題。
在消耗掉幾千個腦細胞后,我想到另外一種思路。既然不能將這個變量指向新的對象,那就干脆重用這個對象吧。我在每次刪除的時候,將被刪除的節(jié)點放入一個隊列,然后在重新加載場景的時候?qū)⑺星懊鎰h除過的節(jié)點再加進來就是了。
實現(xiàn)代碼如下:
func initGraph(){
if nil == graph {
graph = GKGridGraph(fromGridStartingAt: int2(0, 0), width: Int32(gridColumns), height: Int32(gridRows), diagonalsAllowed: false)
} else {
if removedNodes.count > 0 {
for node in removedNodes {
if false == graph.nodes?.contains(node){
graph.addNodes([node])
graph.connectNodeToAdjacentNodes(node)
}
}
removedNodes.removeAll()
}
}
}
經(jīng)過驗證,這個方法可以完美解決這個問題。
如果你恰好也要用GKGridGraph,并且很幸運的看到了我的這篇文字,說不定可以節(jié)省你幾千個腦細胞呢:)