7

Apple の新しい GameplayKit について、おそらくばかげた質問があります。

ゲーム用に 2D グリッドベースのノード レイアウトを作成しています。私は主に の機能が気に入っていますがGKGraphNode2D、1 つの方法で微調整したいと考えています。特定の種類のノード ペアをトラバースするときに、条件付きでペナルティを追加したいと考えています。言い換えれば、いくつかのノードを単純な方法で接続し、いくつかのノードを接続して、それらの通過距離がアプリによって変更されるようにしたいと考えています。

GKGraphNode2Dサブクラス化とオーバーライドは完璧に機能する-costToNode:と思いました! -estimatedCostToNode:によって提供された値を返すsuperこともあれば、ゲームに合わせて微調整することもあります。これら 2 つのメソッドはGKGraphNode、 のスーパークラスである のメソッドですGKGraphdNode2D

残念ながら、これを実行しようとすると、サブクラスで呼び出されないように-costToNode:見えます-estimatedCostToNode:。これらのメソッドは、一連のサブクラス オブジェクトを含むオブジェクトを呼び出したGKGraphNode2Dときに呼び出されることを期待しています。-findPathFromNode:toNode:GKGraphGKGraphNode2D

私は何を間違っていますか?

編集:

以下は私のコードです。

次のように、のサブクラスであるCheapNodeとの2 つのクラスを作成します。ExpensiveNodeGKGraphNode2D

@import UIKit;
@import GameplayKit;

@interface CheapNode : GKGraphNode2D
@end

@implementation CheapNode

- (float)estimatedCostToNode:(GKGraphNode *)node {
    return 1;
}

- (float)costToNode:(GKGraphNode *)node {
    return 1;
}

@end

@import UIKit;
@import GameplayKit;

@interface ExpensiveNode : GKGraphNode2D
@end

@implementation ExpensiveNode

- (float)estimatedCostToNode:(GKGraphNode *)node {
    return 100;
}

- (float)costToNode:(GKGraphNode *)node {
    return 100;
}

@end

次に、テストで、いくつかのノードを作成して接続し、グラフに追加して、findPathFromNode:toNode:メッセージをグラフに送信しました。次に、グラフが見つけたパスを確認しましたが、期待したものは見つかりませんでした。

- (void)testNodeCostsUsed {
    /*
     This is the graph we are creating:

     A---B---C
     |       |
     F---E---D

     where all of the nodes are `CheapNode` objects, except 'B', which is an
     `ExpensiveNode` object.

     This test finds a path from node A to node C.

     If the cost methods in the `CheapNode` and `ExpensiveNode` subclasses
     are used, the route going from A to C around B (down, then right, then up)
     should be used, since the cost of going from B to C is 100, and the cost of
     going from any other node to any other node is 1 
     (see implementation of these classes).

     Instead, we see `GKGraph` choosing the "shortest" route in terms of number
     of nodes, from the top left immediately to the right to the top right.
     */

    CheapNode     *nodeA = [[CheapNode alloc]     initWithPoint:(vector_float2){0, 0}];
    ExpensiveNode *nodeB = [[ExpensiveNode alloc] initWithPoint:(vector_float2){1, 0}];
    CheapNode     *nodeC = [[CheapNode alloc]     initWithPoint:(vector_float2){2, 0}];
    CheapNode     *nodeD = [[CheapNode alloc]     initWithPoint:(vector_float2){2, 1}];
    CheapNode     *nodeE = [[CheapNode alloc]     initWithPoint:(vector_float2){1, 1}];
    CheapNode     *nodeF = [[CheapNode alloc]     initWithPoint:(vector_float2){0, 1}];

    [nodeA addConnectionsToNodes:@[ nodeB, nodeF ] bidirectional:YES];
    [nodeC addConnectionsToNodes:@[ nodeB, nodeD ] bidirectional:YES];
    [nodeE addConnectionsToNodes:@[ nodeF, nodeD ] bidirectional:YES];

    NSArray *allNodes = @[ nodeA, nodeB, nodeC, nodeD, nodeE, nodeF ];

    GKGraph *graph = [GKGraph graphWithNodes:allNodes];
    NSArray *nodes = [graph findPathFromNode:nodeA toNode:nodeC];

    NSArray *expectedPath   = @[ nodeA, nodeF, nodeE, nodeD, nodeC ];
    NSArray *prohibitedPath = @[ nodeA, nodeB, nodeC ];

    XCTAssert([nodes isEqualToArray:expectedPath], @"");
    XCTAssertFalse([nodes isEqualToArray:prohibitedPath], @"");
}

このテスト ケースは失敗します。estimatedCostToNode:また、 andがサブクラスcostToNode:に送信されないことにも気付きましたGKGraphNode2D(ログ ステートメントとブレークポイントで確認)。

この問題を示すサンプル プロジェクトを次に示します。Xcode の最新の開発者ベータ版 (2015 年 8 月 31 日現在、Xcode ベータ 6) でビルドおよび実行する必要があります。

編集2:

誰かが複製に興味がある場合は、この StackOverflow の質問のサンプル コードと説明をバグ ( http://www.openradar.me/22524760 ) として提出しました。iOS 9 がリリースされた後もバグが続く場合は、開発者サポート チケットを使用してこの問題の解決を試みます。

編集3:

Apple は、Developer Support Ticket で私に返事をくれました。彼らはこれがバグであることを認めており、(私が知る限り) iOS 9.2 ベータ 2 (7C46t) で修正されているようです。

編集4:

このフレームワークの別のバグを説明するために、サンプル プロジェクトを更新しました。

4

1 に答える 1

2

Apple は、この問題に関連する私の開発者サポート チケットに応答し、これは既知の問題であり、2015 年 11 月 3 日にリリースされた iOS SDK 9.2 ベータ 2 で修正される可能性があることを教えてくれました 9.2b2 をパスしたので、そのバージョンでこの問題が解決されることを期待しています。

于 2015-11-04T20:14:16.897 に答える