3

少し前に、Apple は GameplayKit 要素を Xcode の Scene Editor に導入しました。これは素晴らしいことです。ただし、ナビゲーション グラフ要素に問題があるようです。 シーン エディタのナビゲーション グラフ

私が達成しようとしているのは、Scene Editor から GKGraph を描画し、それをコードで取得して、パスファインディングのベースとして使用することです。

そこで、最初に GKGraph を描画します。

シーン エディター描画 GKGraph

次に、次のように GameScene.swift で取得します。

graph = self.graphs.values.first

ここで、graphsは、Scene Editor からの GKGraphs を格納するために Apple によって事前定義された配列です。ここまでは順調ですね。

次に、プレーヤーが画面上のタップ位置へのパスを見つけられるようにします。このために、次のコールバック メソッドで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 によって返されるパスにstartNodeendNodeのみが含まれていることです。つまり、プレイヤーは事前に描画された GKGraph の上をまったく歩かず、endNodeまでまっすぐ歩きます。

注: 初めてNSLog(graph.nodes.debugDescription)を実行すると、事前に描画された 10 個のノードがすべて一覧表示されます。graph.connectToLowestCostNodeの後に再度実行すると、12 個のノードがすべて取得されます。したがって、私のグラフには経路探索に必要なすべてが含まれているようです。

何が問題だと思いますか?パスを定義するために、graph.findPathが事前に描画された 10 個のノードを使用しないのはなぜですか? あなたの答えは大歓迎です。

4

1 に答える 1

3

Scene Editor から作成した GKGraph でGameplayKit の.findPathメソッドを呼び出すと、正しく動作しないようです。私がしたことは、事前に描画された 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 ノードすべてを考慮して生成されたパスが含まれるようになりました。

まとめ: Scene Editor で作成されたナビゲーション グラフをパスファインディングに直接使用することはできません。私の解決策は、最初にそのノードをプログラムで作成された GKGraph に複製し、次に最新のものを使用して残りを行うことでした。

于 2016-12-18T17:51:31.713 に答える