对于苹果的新GameplayKit,我可能有一个愚蠢的问题。

我正在为我的游戏创建一个基于2D网格的节点布局。我最喜欢GKGraphNode2D的功能,但想以一种方式对其进行调整。我想在遍历某种类型的节点对时有条件地增加一个惩罚。换句话说,我希望某些节点以直截了当的方式连接,而某些节点则连接成它们的遍历距离可以由我的应用程序修改。

我认为子类化GKGraphNode2D并覆盖-costToNode:-estimatedCostToNode:会完美地工作!有时我会返回super提供的值,并在其他时间为我的游戏进行调整。这两个方法是GKGraphNode的父类(super class)GKGraphdNode2D的方法。

不幸的是,当我尝试执行此操作时,似乎从未在-costToNode:子类上调用-estimatedCostToNode:GKGraphNode2D。我希望在对包含一堆-findPathFromNode:toNode:子类对象的GKGraph对象调用GKGraphNode2D时调用这些方法。

我究竟做错了什么?

编辑:

以下是我的代码。

创建两个类CheapNodeExpensiveNode,它们是GKGraphNode2D的子类,如下所示:

@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:costToNode:从未发送到我的GKGraphNode2D子类(已通过日志语句和断点验证)。

Here是演示此问题的示例项目。它应该在最新的Xcode开发人员beta(截至2015年8月31日,Xcode beta 6)上构建并运行。

编辑2:

如果有人对欺骗感兴趣,我已经在这个StackOverflow问题中将示例代码和描述作为错误(http://www.openradar.me/22524760)提交了。如果在发布iOS 9之后该错误仍然存​​在,我将使用开发人员支持票证尝试解决此问题。

编辑3:

苹果在我的开发人员支持票上给了我答复。他们承认这是一个错误,据我所知,它似乎已在iOS 9.2 beta 2(7C46t)中修复。 🎉

编辑4:

我已经更新了sample project,以使用该框架说明另一个bug

最佳答案

苹果回应了我与该问题相关的开发人员支持票,并告诉我这是一个已知问题,并且2015年11月3日发布的iOS SDK 9.2 beta 2中有潜在的修复。在9.2b2中,因此我希望该版本能够解决此问题。

10-08 15:04