GameplayKit GKPolygonObstacle 不适用于 GKGoal

GameplayKit GKPolygonObstacle Not Working With GKGoal

与我发布的问题类似 here,我现在意识到这个问题比我预期的更微不足道,因为这适用于 GameplayKit 的某些元素,但不适用于其他元素..

我有一个障碍,一个 SKNode,我试图将其定义为一个可以被代理使用的 GKPolygonObstacle,一个 GKAgent2D,作为要避免的障碍搬进SKScene时我已经设置好了。

我调查了 Apple's AgentsCatalog 以了解他们如何使用 GKObstacleGameplayKit 方法中的代理:

goalToAvoidObstacles:(nonnull NSArray<GKObstacle *> *) maxPredictionTime:(NSTimeInterval)

当我在自己的项目中使用以下代码创建 GKCircleObstacle 对象时,我发现代理很好地导航并且 很好地避开了 这些圆形障碍物取决于我给它的权重(重要性级别)。

这是我正在使用的代码:

NSArray<GKObstacle *> *obstacles2 = @[
    [self addObstacleAtPoint:CGPointMake(CGRectGetMidX(self.frame),
                             CGRectGetMidY(self.frame) + 150)],
    [self addObstacleAtPoint:CGPointMake(CGRectGetMidX(self.frame) - 200,
                             CGRectGetMidY(self.frame) - 150)],
    [self addObstacleAtPoint:CGPointMake(CGRectGetMidX(self.frame) + 200,
                             CGRectGetMidY(self.frame) - 150)], ];
  
enemy.avoidGoal = [GKGoal goalToAvoidObstacles:obstacles2 maxPredictionTime:1];
[enemy.agent.behavior setWeight:100 forGoal:enemy.avoidGoal];

使用以下创建和添加这些障碍的方法:(这是直接从 Apple 的 AgentsCatalog 源代码中提取的)

- (GKObstacle *)addObstacleAtPoint:(CGPoint)point {
    SKShapeNode *circleShape = [SKShapeNode shapeNodeWithCircleOfRadius:50];
    circleShape.lineWidth = 2.5;
    circleShape.fillColor = [SKColor grayColor];
    circleShape.strokeColor = [SKColor redColor];
    circleShape.zPosition = 1;
    circleShape.position = point;
    [self addChild:circleShape];

    GKCircleObstacle *obstacle = [GKCircleObstacle obstacleWithRadius:50];
    obstacle.position = (vector_float2){point.x, point.y};

    return obstacle;
}

这很有效,因为敌人在试图移动到场景中某个不断变化的位置时会避开这些圆圈。

问题

当我尝试通过使用 GKPolygonObstacle 对象代替 GKCircleObstacle 对象来重新创建此 GKGoal 行为时,敌方代理似乎无法将多边形障碍识别为要避免的障碍为行为目标。以下是我尝试添加这些障碍的方式:

NSArray<GKObstacle *> *obstacles = [SKNode obstaclesFromNodePhysicsBodies:innerMapArray];

// Take this array of GKPolygonObstacle objects and add it 
// to the GKGoal of the enemy as obstacles to avoid

enemy.avoidGoal = [GKGoal goalToAvoidObstacles:obstacles maxPredictionTime:1];
[enemy.agent.behavior setWeight:100 forGoal:enemy.avoidGoal];

最令人沮丧的是,我知道数组正确地创建了 NSArrayGKPolygonObstacle 对象,因为我也使用这种方法进行寻路(在我决定痛苦地实施 GameplayKit 并且它是寻求、避免和徘徊的目标)。这是我如何使用这个 innerMapArray:

- (NSArray *)findPathWithNode:(SKNode *)nodeToFindPath {
    
    NSArray *obstacles = [SKNode obstaclesFromNodePhysicsBodies:innerMapArray];
    GKObstacleGraph *graph = [GKObstacleGraph graphWithObstacles:obstacles bufferRadius:35.0f];


    // Set up enemy and target
    GKGraphNode2D *target = [GKGraphNode2D nodeWithPoint:vector2((float)character.position.x, (float)character.position.y)];
    GKGraphNode2D *enemy = [GKGraphNode2D nodeWithPoint:vector2((float)nodeToFindPath.position.x, (float)nodeToFindPath.position.y)];
    
    [graph connectNodeUsingObstacles:enemy];
    [graph connectNodeUsingObstacles:target];
    
    /// Create tracking path
    NSArray *pathPointsFound = [graph findPathFromNode:enemy toNode:target];

    
    return pathPointsFound;
}

这个方法非常好returns最有效的路径应该包括绕过障碍物的点我告诉敌人在试图到达一个位置时要避免。

如果有人能帮我弄清楚如何将这些 SKNode 对象转换为可以接受的障碍,并在 GKGoal 中注册,我将不胜感激。谢谢。

这是一个非常奇怪/简单的答案,恐怕我现在遇到了被敌人避开的障碍(至少不是..)。

  • GKGoal 以避开障碍物非常 low maxPredictionTime (t < 10) 似乎让智能体完全忽略障碍物。任何 10 或更大的预测时间 + 100+ 的权重似乎都会导致正确的行为。