I am using GKAgents, GKGoals and GKBehaviours, but I'm getting leaked memory between my Behaviour and Component. I think images and code may better explain my problem:
In my entity manager I return all drone entities:
func droneEntities() -> [GKAgent2D] {
for componentSystem in componentSystems {
if componentSystem.componentClass is DroneMoveComponent.Type {
let components = componentSystem.components
return components.flatMap{ component in
return component as? GKAgent2D
}
}
}
return []
}
My Dronemovecomponent:
import SpriteKit
import GameplayKit
class DroneMoveComponent: GKAgent2D, GKAgentDelegate {
weak var entityManager: EntityManager?
init(entityManager: EntityManager) {
self.entityManager = entityManager
super.init()
delegate = self
self.maxSpeed = 50.0
self.mass = 0.01
self.radius = 16
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func agentWillUpdate(_ agent: GKAgent) {
guard let spriteComponent = entity?.component(ofType: SpriteComponent.self) else {
return
}
position = vector_float2(Float(spriteComponent.node.position.x), Float(spriteComponent.node.position.y))
}
func agentDidUpdate(_ agent: GKAgent) {
guard let spriteComponent = entity?.component(ofType: SpriteComponent.self) else {
return
}
spriteComponent.node.position = CGPoint(x: CGFloat(position.x), y: CGFloat(position.y))
}
override func update(deltaTime seconds: TimeInterval) {
super.update(deltaTime: seconds)
if let controlledComponent = entityManager?.playerEntity?.component(ofType: ControlledComponent.self) {
let droneEntities = entityManager?.droneEntities().filter{$0 != self}
behavior = DroneMoveBehaviour(seek: controlledComponent, avoid: (entityManager?.berkEntities())!, drones: droneEntities!)
}
}
}
My DroneMoveBehaviour:
import GameplayKit
import SpriteKit
class DroneMoveBehaviour: GKBehavior {
init(seek: GKAgent, avoid: [GKAgent], drones: [GKAgent]) {
super.init()
setWeight(500, for: GKGoal(toReachTargetSpeed: 50))
setWeight(100, for: GKGoal(toInterceptAgent: seek, maxPredictionTime: 10))
setWeight(1000, for: GKGoal(toAvoid: avoid, maxPredictionTime: 10))
setWeight(1000, for: GKGoal(toAvoid: drones, maxPredictionTime: 10))
}
}
Here is an image of my memory graph:
I have another set of components and behaviours leaking in the same way, I figured if somebody could help me understand how to fix this, I could go on and correct the other ones myself.
Should the array contain weak references? Should I switch to NSPointerArray? Or am I overlooking something else? Any guidance here will be greatly appreciated, thanks.
Setting the DroneMoveComponents behaviour on every update is not necessary! Moving this set only once in the constructor seems to prevent the leaks.