与我在这里发布的问题类似,我现在意识到这个问题比我预期的更微不足道,因为这适用于某些元素GameplayKit
但不适用于其他元素。
我有一个障碍物 an SKNode
,我试图将它定义为一个GKPolygonObstacle
可以被代理使用的 a GKAgent2D
,作为在SKScene
我设置的移动时要避免的障碍物。
我查看了Apple 的 AgentsCatalog以了解他们如何GKObstacle
在方法中使用代理GameplayKit
:
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;
}
当敌人试图移动到场景中某个变化的位置时,它会避开这些圆圈,这很有效。
问题
当我尝试GKGoal
通过使用GKPolygonObstacle
对象代替对象来重新创建此行为时GKCircleObstacle
,敌方代理似乎无法将多边形障碍识别为行为目标要避免的障碍。以下是我尝试添加这些障碍的方法:
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];
最令人沮丧的是,我知道数组正确地创建了一个NSArray
对象GKPolygonObstacle
,因为我也使用这种方法进行寻路(在我决定痛苦地实现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;
}
这个方法很好地返回了最有效的路径应该包括绕过障碍物的点,我告诉敌人在试图到达一个位置时要避开。
- 所以真正的问题变成了:为什么
GKGoal
接受GKCircleObstacle
对象而不接受GKPolygonObstacle
对象?
如果有人可以帮助我弄清楚如何将这些SKNode
对象转换为注册的可接受的障碍物,GKGoal
我将非常感激。谢谢你。