GameplayKit > Scene Editor Navigation Graph > 如何使用它来寻路?
GameplayKit > Scene Editor Navigation Graph > How to use it for pathfinding?
不久前,Apple 将 GameplayKit 元素引入到 Xcode 的场景编辑器中,这很棒。但是,我似乎对 Navigation Graph 元素有疑问:
我试图实现的是从场景编辑器中绘制一个 GKGraph,在代码中检索它,并将其用作寻路的基础。
所以我先画了一个GKGraph:
然后我像这样在 GameScene.swift 中检索它:
graph = self.graphs.values.first
其中 graphs 是 Apple 预定义的数组,用于存储场景编辑器中的 GKGraphs。到目前为止一切顺利。
然后我想让玩家在屏幕上找到点击位置的路径。为此,我使用 UITapGestureRecognizer 和以下回调方法:
var moving = false
func moveToLocation(recognizer: UITapGestureRecognizer) {
var tapLocation = recognizer.location(in: recognizer.view!)
tapLocation = self.convertPoint(fromView: tapLocation)
guard (!moving) else { return }
moving = true
let startNode = GKGraphNode2D(point: vector_float2(Float(player.visualComponent.node.position.x), Float(player.visualComponent.node.position.y)))
let endNode = GKGraphNode2D(point: vector_float2(Float(tapLocation.x), Float(tapLocation.y)))
NSLog(graph.nodes.debugDescription)
graph.connectToLowestCostNode(node: startNode, bidirectional: true)
graph.connectToLowestCostNode(node: endNode, bidirectional: true)
NSLog(graph.nodes.debugDescription)
let path: [GKGraphNode] = graph.findPath(from: startNode, to: endNode)
guard path.count > 0 else { moving = false; return }
var actions = [SKAction]()
for node: GKGraphNode in path {
if let point2d = node as? GKGraphNode2D {
let point = CGPoint(x: CGFloat(point2d.position.x), y: CGFloat(point2d.position.y))
let action = SKAction.move(to: point, duration: 1.0)
actions.append(action)
}
}
graph.remove([startNode, endNode])
// Convert those actions into a sequence action, then run it on the player node.
let sequence = SKAction.sequence(actions)
player.visualComponent.node.run(sequence, completion: { () -> Void in
// When the action completes, allow the player to move again.
self.moving = false
})
}
使用这种方法,我让玩家前往点击位置。问题是 GameplayKit 返回的路径只包括 startNode 和 endNode,这意味着玩家不会走在预先绘制的完全没有 GKGraph,而是直接走到 endNode.
注意:当我第一次 运行 NSLog(graph.nodes.debugDescription) 它列出了所有 10 个预先绘制的节点。当我在 graph.connectToLowestCostNode 之后再次 运行 时,我得到了所有 12 个节点。所以我的图表似乎包含了寻路所需的一切。
您认为问题是什么?为什么graph.findPath不使用预先绘制的10个节点来定义路径?非常感谢您的回答。
似乎 GameplayKit 的 .findPath 方法在从场景编辑器创建的 GKGraph 上调用时无法正常工作。我所做的是,我将节点从预先绘制的 GKGraph 克隆到以编程方式创建的 GKGraph:
let newGraph = GKGraph()
for drawnNode in graph.nodes! {
newGraph.add([drawnNode])
}
然后,.findPath 就可以正常工作了:
newGraph.connectToLowestCostNode(node: startNode, bidirectional: true)
newGraph.connectToLowestCostNode(node: endNode, bidirectional: true)
let path: [GKGraphNode] = newGraph.findPath(from: startNode, to: endNode)
变量path
现在包含考虑所有10 + 2个节点生成的路径。
总结:您不能直接使用在场景编辑器中创建的导航图进行寻路。我的解决方案是首先将其节点克隆到以编程方式创建的 GKGraph,然后使用最新的来完成其余的工作。
不久前,Apple 将 GameplayKit 元素引入到 Xcode 的场景编辑器中,这很棒。但是,我似乎对 Navigation Graph 元素有疑问:
我试图实现的是从场景编辑器中绘制一个 GKGraph,在代码中检索它,并将其用作寻路的基础。
所以我先画了一个GKGraph:
然后我像这样在 GameScene.swift 中检索它:
graph = self.graphs.values.first
其中 graphs 是 Apple 预定义的数组,用于存储场景编辑器中的 GKGraphs。到目前为止一切顺利。
然后我想让玩家在屏幕上找到点击位置的路径。为此,我使用 UITapGestureRecognizer 和以下回调方法:
var moving = false
func moveToLocation(recognizer: UITapGestureRecognizer) {
var tapLocation = recognizer.location(in: recognizer.view!)
tapLocation = self.convertPoint(fromView: tapLocation)
guard (!moving) else { return }
moving = true
let startNode = GKGraphNode2D(point: vector_float2(Float(player.visualComponent.node.position.x), Float(player.visualComponent.node.position.y)))
let endNode = GKGraphNode2D(point: vector_float2(Float(tapLocation.x), Float(tapLocation.y)))
NSLog(graph.nodes.debugDescription)
graph.connectToLowestCostNode(node: startNode, bidirectional: true)
graph.connectToLowestCostNode(node: endNode, bidirectional: true)
NSLog(graph.nodes.debugDescription)
let path: [GKGraphNode] = graph.findPath(from: startNode, to: endNode)
guard path.count > 0 else { moving = false; return }
var actions = [SKAction]()
for node: GKGraphNode in path {
if let point2d = node as? GKGraphNode2D {
let point = CGPoint(x: CGFloat(point2d.position.x), y: CGFloat(point2d.position.y))
let action = SKAction.move(to: point, duration: 1.0)
actions.append(action)
}
}
graph.remove([startNode, endNode])
// Convert those actions into a sequence action, then run it on the player node.
let sequence = SKAction.sequence(actions)
player.visualComponent.node.run(sequence, completion: { () -> Void in
// When the action completes, allow the player to move again.
self.moving = false
})
}
使用这种方法,我让玩家前往点击位置。问题是 GameplayKit 返回的路径只包括 startNode 和 endNode,这意味着玩家不会走在预先绘制的完全没有 GKGraph,而是直接走到 endNode.
注意:当我第一次 运行 NSLog(graph.nodes.debugDescription) 它列出了所有 10 个预先绘制的节点。当我在 graph.connectToLowestCostNode 之后再次 运行 时,我得到了所有 12 个节点。所以我的图表似乎包含了寻路所需的一切。
您认为问题是什么?为什么graph.findPath不使用预先绘制的10个节点来定义路径?非常感谢您的回答。
似乎 GameplayKit 的 .findPath 方法在从场景编辑器创建的 GKGraph 上调用时无法正常工作。我所做的是,我将节点从预先绘制的 GKGraph 克隆到以编程方式创建的 GKGraph:
let newGraph = GKGraph()
for drawnNode in graph.nodes! {
newGraph.add([drawnNode])
}
然后,.findPath 就可以正常工作了:
newGraph.connectToLowestCostNode(node: startNode, bidirectional: true)
newGraph.connectToLowestCostNode(node: endNode, bidirectional: true)
let path: [GKGraphNode] = newGraph.findPath(from: startNode, to: endNode)
变量path
现在包含考虑所有10 + 2个节点生成的路径。
总结:您不能直接使用在场景编辑器中创建的导航图进行寻路。我的解决方案是首先将其节点克隆到以编程方式创建的 GKGraph,然后使用最新的来完成其余的工作。