0

Using GameplayKit, I'm trying to make an enemy character pursue the player while avoiding obstacles in a SpriteKit game.

However, the agent in agentDidUpdate(_:) has a position and velocity of nan.

Here's what I'm doing now:

  1. Configure the obstacles:
//node is defined here
let obstacle = GKCircleObstacle(radius: Float(node.size.width*0.5))
obstacle.position = vector_float2(x: Float(node.position.x), y: Float(node.position.y))
levelObstacles.append(obstacle)
  1. Configure a GKEntity (etc.) for the player SKSpriteNode, saving a reference to the component and agent for use in #3:
//node is defined here
let entity1 = GKEntity()
heroAgent = GKAgent2D()
heroComponent = GKSKNodeComponent(node: node)
heroAgent.delegate = self // <-- self is a GKAgentDelegate
node.entity = entity1
heroEntity = entity1
if let comp = heroComponent {
    entity1.addComponent(comp)
    entity1.addComponent(heroAgent)
}
  1. Configure a GKEntity (etc.) for the enemy SKSpriteNode, using the saved hero component and agent to set up the necessary behaviors:
//node is defined here
let entity = GKEntity()
let agent = GKAgent2D()
let avoid = GKGoal(toAvoid: levelObstacles, maxPredictionTime: 5.0)
let pursue = GKGoal(toInterceptAgent: heroAgent, maxPredictionTime: 5.0)
nodeComponent = GKSKNodeComponent(node: node)
agent.behavior = GKBehavior(goals: [avoid, pursue], andWeights: [100.0, 50.0])
agent.delegate = self // <-- self is a GKAgentDelegate
node.entity = entity
if let comp = nodeComponent {
    entity.addComponent(comp)
    entity.addComponent(agent)
}
nodeEntity = entity
  1. In the SKScene's update(_:) method, call the enemy entity's update(deltaTime:) method:
nodeEntity?.update(deltaTime: currentTime-lastFrameTime)
  1. Print the agent's position and velocity in agentDidUpdate(_:):
func agentDidUpdate(_ agent: GKAgent) {
   if let a = agent as? GKAgent2D {
      print("agent position: \(a.position), agent velocity: \(a.velocity)") //Prints a position and velocity of "-nan"
   }
}

Question: Why are the agent's position and velocity nan inside agentDidUpdate(_:), and how do I solve the problem?

Update: The problem is apparently related to GKGoal(toInterceptAgent:maxPredictionTime:). If I use a different goal, like GKGoal(toFleeAgent:) for example, there are actual values available in agentDidUpdate(_:).

West1
  • 1,430
  • 16
  • 27

1 Answers1

0

I was able to get this working by setting the player agent's position to the actual SpriteKit node's position inside the SKScene's update(_:) method, like this:

heroAgent.position = vector_float2(x: Float(mainCharacter?.position.x ?? 0.0), y: Float(mainCharacter?.position.y ?? 0.0))

I'm not really sure why that worked, but it did.

West1
  • 1,430
  • 16
  • 27