【问题标题】:Obstacles With GameplayKitGameplayKit 的障碍
【发布时间】:2016-07-25 14:56:22
【问题描述】:

这是我的问题:

  • 如何将SKSpriteNodearray 转换为GKObstacles 数组,以便代理可以通过使用goalToAvoidObstacles:(nonnull NSArray<GKObstacle *> *) maxPredictionTime:(NSTimeInterval)/来适当地避免这些障碍?

似乎我创建GKObstacle 数组的方式不允许GKGoal 正确地将这些识别为障碍物,无论我对目标赋予多大权重。

我目前有几个SKNodes 添加到SKScene chapterScene。这些节点中的每一个都添加到我存储的名为 obstaclesArray 的数组中。我已经通过以下方式设置了一个运行良好的测试:

工作障碍

- (void)didMoveToView:(nonnull SKView *)view {
    [super didMoveToView:view];

    // Add three obstacles in a triangle formation around the center of the scene.
    NSArray<GKObstacle *> *obstacles = @[
                                         [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)],
                                         ];

    // The player agent follows the tracking agent.
    self.player = [[OPlayer alloc] initWithScene:self
                                                radius:50
                                              position:CGPointMake(CGRectGetMidX(self.frame),
                                                                   CGRectGetMidY(self.frame))];
    self.player.agent.behavior = [[GKBehavior alloc] init];
    [self.agentSystem addComponent:self.player.agent];

    // Create the seek goal, but add it to the behavior only in -setSeeking:.
    self.seekGoal = [GKGoal goalToSeekAgent:self.character];

    // Add an avoid-obstacles goal with a high weight to keep the agent from overlapping the obstacles.
    [self.player.agent.behavior setWeight:100 forGoal:[GKGoal goalToAvoidObstacles:obstacles maxPredictionTime:1]];

}

- (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;
}

虽然这工作得很好,但我遇到的问题是我无法识别我作为障碍物的SKNode 身体数组的行为。我只能让这些手动创建的GKCircleObstacle 项目注册为代理避免的有效障碍。这是一个问题的原因是因为我依赖的许多障碍实际上不是简单的圆圈,而是多边形结构有些复杂,有些更简单。尽管如此,我正在尝试以下操作,但我的代理似乎并没有以这种方式避免SKNode 的任何障碍:

没有工作障碍

NSArray *obstacles = [SKNode obstaclesFromNodePhysicsBodies:obstaclesArray];

/*
 The other code seen above
 */

// Add an avoid-obstacles goal with a high weight to keep the agent from overlapping the obstacles.
[self.player.agent.behavior setWeight:100 forGoal:[GKGoal goalToAvoidObstacles:obstacles maxPredictionTime:1]];

不幸的是,这似乎不起作用,因为无论我将权重设置多高,代理都不会响应避开障碍物。这是我传递给它的数组的日志:

2016-07-24 22:32:24.907 <GAME>[1516:475581] obstacles: (
    "<GKPolygonObstacle: 0x14d20d70>",
    "<GKPolygonObstacle: 0x14d20e10>",
    "<GKPolygonObstacle: 0x14d20ba0>",
    "<GKPolygonObstacle: 0x14d20bb0>",
    "<GKPolygonObstacle: 0x14d20bc0>",
    "<GKPolygonObstacle: 0x14d20a60>",
    "<GKPolygonObstacle: 0x14d208b0>",
    "<GKPolygonObstacle: 0x14d207d0>",
    "<GKPolygonObstacle: 0x14d20a70>"
)

其中的每一个都已被清晰且适当地初始化并添加到场景中。实际上,这些元素中的每一个都使用 SpriteKit didBeginContact:(SKPhysicsContact *)contact 方法进行响应,因此节点似乎正在正确处理它们应该拥有的边界。

如果有人知道我做错了什么或将这些“障碍节点”中的每一个变成GKObstacle 的更好方法,我将不胜感激。提前致谢!

更新:这是一个我正在测试的带有物理体的节点:

        SKSpriteNode *innerMap1 = [SKSpriteNode spriteNodeWithImageNamed:@"test"];
        innerMap1.physicsBody = [SKPhysicsBody bodyWithTexture:[SKTexture textureWithImageNamed:@"test"] size:CGSizeMake(innerMap1.frame.size.width*0.92, innerMap1.frame.size.height*0.92)];
        innerMap1.position = CGPointMake(-220, -140);
        innerMap1.physicsBody.dynamic = NO;

        [chapterSKSpriteNodes addObject:innerMap1];

这是skView.showsPhysics = YES; 的身体外观:

所以我知道物理身体是我需要的。但是,当我尝试从该主体创建 GKObstacle 时,它在被分配到 AvoidObstacles 目标时似乎没有注册为障碍。

【问题讨论】:

  • Physics body 不是免费的,你需要为你的节点创建它们。我在提供的代码中没有看到这个
  • 抱歉 - 有大量带有 PB 的节点,所以我没有为我提供制作它们的代码。我将在我的问题的更新中举一个例子
  • 也许您对事件的顺序有疑问?你在obstaclesFromNodePhysicsBodies 之前检查一下数组中的节点是否有实体?
  • 我没有检查这个否,但我现在正尝试使用上图中显示的对象作为障碍,它似乎没有采取..所以从我所看到的从我的设置来看,我假设它确实有一个可以使用的主体
  • 好吧,不要假设,验证物理体是否存在需要一分钟,编写一个 for 循环并检查以确保它们存在。

标签: ios objective-c sprite-kit gameplay-kit


【解决方案1】:

这听起来像是一个错误。您应该检查从 barrierFromNodePhysicsBodies 中返回的数组,并确保您实际上得到了您期望的障碍。我怀疑你不是。

您可以像这样检查障碍物上的相关顶点:

https://developer.apple.com/library/ios/documentation/GameplayKit/Reference/GKPolygonObstacle_Class/index.html#//apple_ref/occ/cl/GKPolygonObstacle

确保它们符合您的预期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 2011-10-16
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    相关资源
    最近更新 更多