最初のオプションを使用しました。つまり、motionComponent 更新関数でターゲットまでの距離を追跡します。
override func update(deltaTime seconds: TimeInterval) {
guard let entity = self.entity as? BaseEntity else { return }
if entity.moving {
let targetPoint = CGPoint(x: 100, y: 100)
let distanceToTarget = distanceFrom(point: point)
if distanceToTarget < GameConfiguration.Movement.targetProximity {
stopMovement(afterTraversing: distanceToTarget)
}
}
}
func distanceFrom(point: CGPoint) -> Float {
guard let entity = self.entity as? BaseEntity else { return CGFloat.greatestFiniteMagnitude }
let dx = point.x - entity.visualComponent.node.position.x
let dy = point.y - entity.visualComponent.node.position.y
return hypotf(Float(dx), Float(dy))
}
エージェントがターゲットに十分近づいたら、stopMovement 関数を実行します。次に、これにより、ターゲットまでの距離を移動するのに必要な時間が計算され (一定の速度で)、エージェントを強制停止するタイミングに関するタイマーが設定されます。
func stopMovement(afterTraversing distance: Float) {
guard let entity = self.entity as? BaseEntity else { return }
guard (entity.moving) else { return }
guard let behavior = entity.agent.behavior as? MovingBehavior else { return }
let timeToTarget = TimeInterval(distance / entity.agent.maxSpeed)
Timer.scheduledTimer(withTimeInterval: timeToTarget, repeats: false, block: {_ in
behavior.stopMoving()
entity.agent.maxSpeed = 0.0
entity.moving = false
})
}
class MovingBehavior: GKBehavior {
var reachMaxSpeed: GKGoal
var followPathGoal: GKGoal
var stopMovingGoal = GKGoal(toReachTargetSpeed: 0.0)
init(path: GKPath, target: GKGraphNode, maxSpeed: Float) {
reachMaxSpeed = GKGoal(toReachTargetSpeed: maxSpeed)
followPathGoal = GKGoal(toFollow: path, maxPredictionTime: 1.0, forward: true)
super.init()
setWeight(1.0, for: reachMaxSpeed)
setWeight(0.8, for: followPathGoal)
setWeight(0.0, for: stopMovingGoal)
}
func stopMoving() {
setWeight(0.0, for: reachMaxSpeed)
setWeight(0.0, for: followPathGoal)
setWeight(1.0, for: stopMovingGoal)
}
}