在Gameplaykit中,如何在GKAgent2D行为中添加延迟GKGoal时间?

时间:2016-01-28 16:19:46

标签: ios swift sprite-kit behavior gameplay-kit

我的GKEntity有一个GKAgent2D组件。它的行为是GKGoaltoWander:toStayOnPath:maxPredictionTime:。实体在场景中不断徘徊;但是,我希望它停止徘徊一段时间。例如,如果实体是一只徘徊的绵羊,我希望它能够定期停止进食,经过一段时间后,又开始徘徊。

更新

实体

addComponent(MoveIdleComponent(maxSpeed: 60, maxAcceleration: 6, radius: Float(node.texture!.size().width * 0.3), entityManager: entityManager))

MoveIdleComponent

class MoveIdleComponent : GKAgent2D, GKAgentDelegate {

let entityManager: EntityManager

init(maxSpeed: Float, maxAcceleration: Float, radius: Float, entityManager: EntityManager) {
    self.entityManager = entityManager
    super.init()
    delegate = self
    self.maxSpeed = maxSpeed
    self.maxAcceleration = maxAcceleration
    self.radius = radius
    print(self.mass)
    self.mass = 0.01
}


func agentWillUpdate(agent: GKAgent) {
    guard let spriteComponent = entity?.componentForClass(SpriteComponent.self) else {
        return
    }

    self.position = float2(spriteComponent.node.position)
}

func agentDidUpdate(agent: GKAgent) {
    guard let spriteComponent = entity?.componentForClass(SpriteComponent.self) else {
        return
    }

    spriteComponent.node.position = CGPoint(position)
}



override func updateWithDeltaTime(seconds: NSTimeInterval) {

    super.updateWithDeltaTime(seconds)

    behavior = WanderBehavoir(targetSpeed: maxSpeed)
}
}

WanderBehavoir:

class WanderBehavoir: GKBehavior {

  init(targetSpeed: Float) {
    super.init()

    if targetSpeed > 0 {
        setWeight(0.5, forGoal: GKGoal(toWander: targetSpeed))
    }
}
}

我该怎么做?

提前致谢

2 个答案:

答案 0 :(得分:1)

似乎没有GKGoal(toEatFood:withFrequency:) API,因此您必须退一步思考如何设置代理的目标以实现您的< / em>目标。

如果您希望代理停止游荡,或者停止跟踪路径,在一段时间内,您想要的就是那些不再是目标的人。 (而且,你希望它停止,当你取消目标时不要继续任何方向和速度,所以你要为速度为零引入toReachTargetSpeed:目标。)

通常有两种方法可以做到这一点:

  • 让你的行为包括漫游,跟随路径和速度(零)目标,权重设置使得漫游和跟随路径超过速度。如果要在漫游+路径行为和停止行为之间切换,请使用setWeight(_:forGoal:)使速度目标超过其他目标。

  • 有一个行为包含漫游和跟踪路径目标,另一个行为具有速度(零)目标,并在您想要在它们之间切换时设置代理的behavior属性。

答案 1 :(得分:0)

好的,我找到了@rickster建议的解决方案。我发布它可以帮助某人。 我添加了暂停值。 如果暂停为真,则速度权重变为1,GKGoal(toReachTargetSpeed: 0)

WanderBehavoir 课程中:

class WanderBehavoir: GKBehavior {

init(targetSpeed: Float, entityManager: EntityManager, pause: Bool) {

    super.init()

    var weightWander : Float = 1.0
    var weightSpeed  : Float = 0.0

    if pause {
        weightWander = 0
        weightSpeed = 1
    }

    //   |  |
    // --A--B--
    //   |  |

    if targetSpeed > 0 {
        let lato = Float(500.0)
        let pts = [vector_float2(-lato,0),vector_float2(+lato,0)]

        let path = GKPath(points: UnsafeMutablePointer(pts), count: pts.count, radius: 980, cyclical: true)

        let obstacleNode = entityManager.nodesWithUnitType(Tree)
        let obstacles = SKNode.obstaclesFromNodePhysicsBodies(obstacleNode)

            setWeight(0.5,          forGoal: GKGoal(toAvoidObstacles: obstacles, maxPredictionTime: 0.5))
            setWeight(0.2,          forGoal: GKGoal(toStayOnPath: path, maxPredictionTime: 0.5))
            setWeight(weightWander, forGoal: GKGoal(toWander: targetSpeed))
            setWeight(weightSpeed,  forGoal: GKGoal(toReachTargetSpeed: 0))
        }
    }
}

在班级 class MoveIdleComponent : GKAgent2D, GKAgentDelegate暂停时,在随机增量时间后切换为true和false

private var lastUpdateInterval: NSTimeInterval = 0
var setPause = true
var randomTimeStop = NSTimeInterval(Int(5...8))
var randomTimeMove = NSTimeInterval(Int(10...20))

override func updateWithDeltaTime(seconds: NSTimeInterval) { 
    super.updateWithDeltaTime(seconds)        

    lastUpdateInterval += seconds

    if setPause {
        if lastUpdateInterval > randomTimeStop {
            setPause = !setPause
            lastUpdateInterval = 0
            randomTimeMove = NSTimeInterval(Int(10...20))
        }
    }
    else {
        if lastUpdateInterval > randomTimeMove {
            setPause = !setPause
            lastUpdateInterval = 0
            randomTimeStop = NSTimeInterval(Int(5...8))
        }

    }
    print("randomTimeMove \(randomTimeMove)")

    behavior = WanderBehavoir(targetSpeed: maxSpeed, entityManager: entityManager, pause: setPause)
}