GameplayKit>让代理在目标跟随路径后停止移动

时间:2016-12-23 15:33:00

标签: ios gameplay-kit

我正在让代理人遵循GKPath,向其行为添加目标toFollow:GKPath。一切正常,但是当到达路径上的目标点时,代理继续以类似8的形状移动。如何在到达GKPath上的目标点时阻止代理漫游?

我想到的一个解决方案是设置另一个目标toReachTargetSpeed:0.0接近目标点时。但是,我不确定最佳做法是什么,因为没有内置的方法来确定目标何时“完成”。

  1. 我是否使用IF语句检查每次更新时的目标距离:?性能怎么样?
  2. 我是否使用某种GKRule?
  3. 非常感谢您的建议。感谢。

1 个答案:

答案 0 :(得分:1)

我选择了第一个选项,即在movingComponent更新功能中跟踪目标距离:

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)
    }
}