GameplayKit> Script Graphics Editor> How to use it to find a path?

Apple recently introduced GameplayKit elements for the Xcode script editor, which is great. However, I seem to have problems with the Navigation Graph element: Scene editor navigation graph

What I'm trying to achieve is to draw a GKGraph from the scene editor, get it in the code, and use it as the basis for finding the path.

So first I draw the GKGraph:

Scene Editor filmed by GKGraph

Then I retrieve it in GameScene.swift as follows:

graph = self.graphs.values.first 

where the graphs are Apple's predefined array for storing GKGraphs from the scene editor. So far so good.

Then I want the player to find the path to the location of the tap on the screen. For this, I use UITapGestureRecognizer with the following callback method:

 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 }) } 

Using this method, I force the player to go to the connection point. The problem is that the path returned by GameplayKit includes only startNode and endNode, which means that the player doesn’t walk the previously drawn GKGraph at all, but goes straight to endNode.

Note. When I first start NSLog (graph.nodes.debugDescription), it lists all 10 pre-drawn nodes. When I run it again after graph.connectToLowestCostNode, I get all 12 nodes. Therefore, my schedule contains everything you need to find a path.

What do you think is the problem? Why doesn't graph.findPath use pre-drawn 10 nodes to determine the path? Your answers will be highly appreciated.

+3
source share
1 answer

It seems that the GameplayKit.findPath method does not work properly when called on a GKGraph created from the scene editor. What I did was, I cloned the nodes from the previously drawn GKGraph to the programmatically created GKGraph:

 let newGraph = GKGraph() for drawnNode in graph.nodes! { newGraph.add([drawnNode]) } 

Then, .findPath works fine on it:

 newGraph.connectToLowestCostNode(node: startNode, bidirectional: true) newGraph.connectToLowestCostNode(node: endNode, bidirectional: true) let path: [GKGraphNode] = newGraph.findPath(from: startNode, to: endNode) 

The path variable now contains the path generated taking into account all 10 + 2 nodes.

Completion: You cannot directly use the navigation chart created in the scene editor to find the path. My solution was to first clone its nodes of the software-created GKGraph, and then use the latter for the rest.

+2
source

Source: https://habr.com/ru/post/1269289/


All Articles