概要
GKAgent2D は SpriteKit 上で CPU 用の AI を作成することができるクラスです
特定のオブジェクトを追いかけたり、特定のオブジェクトを近づけたりできます
今回は最低限の使い方を紹介します
環境
- macOS 10.13.4
- Xcode 9.3 (9E145)
プロジェクト作成
Game 用のプロジェクトを作成しましょう
「Integrate GameplayKit」はチェックしないで OK です
エージェント作成
まずエージェントを作成しましょう
今回は 2 つのエージェントを定義しますがいくつ定義しても OK です
class GameScene: SKScene {
var agent1 = GKAgent2D()
var agent2 = GKAgent2D()
override func didMove(to view: SKView) {
agent1.position = vector_float2(x: 0, y: 0)
agent2.position = vector_float2(x: Float(self.frame.maxX), y: Float(self.frame.maxY))
}
}
GKAgent2D クラスのオブジェクトを生成します
生成したらポジションを設定します
今回は真ん中と画面の右端を設定し、右端のエージェントが真ん中のエージェントに移動するようにします
ゴールと行動を設定
続いてエージェントの行動を設定します
didMove に続けて以下を追加しましょう
agent2.behavior = GKBehavior(goals: [GKGoal(toSeekAgent: agent1)], andWeights: [100])
行動 (GKBehavior) は指定するゴール (GKGoal) を元にどうエージェントが移動するかを設定します
今回は agent2 が agent1 に近づく (シークする) ように行動するので GKGoal(toSeekAgent: agent1)
をゴールに指定し GKBehavior
を設定します
エージェント用の delegate メソッドを追加
エージェントが移動した際にコールされる delegte メソッドを追加します
クラスの外に extension
を使って GameScene
の拡張を行います
extension GameScene: GKAgentDelegate {
func agentDidUpdate(_ agent: GKAgent) {
if let agent2 = agent as? GKAgent2D {
print(agent2.position)
}
}
}
GKAgentDelegate
を継承し agentDidUpdate
を実装しましょう
今回は agent2 が移動するので引数の agent には agent2 の情報が渡ってきます
とりあえず print
しましょう
本来ここでは SKSpriteNode とエージェントがリンクするようにノードの移動や再描画を行います
delegate メソッドが定義できたら didMove に続けて以下を追記しましょう
agent2.delegate = self
これで agent2 が移動するたびに先ほどの agentDidUpdate
が呼ばれるようになります
エージェントを管理するコンポーネントを作成
エージェントは専用のコンポーネントに入れて管理する必要があります
フィールドに以下を追加しましょう
var agentSystem = GKComponentSystem(componentClass: GKAgent2D.self)
これに先ほどの agent2 を入れていきます
didMove
に以下を追記しましょう
agentSystem.addComponent(agent2)
この agentSystem
を操作することで agent2 を操作します
エージェントの更新処理
agentDidUpdate
が呼ばれるように agentSystem
を更新します
GameScene 内に update
を定義しましょう
そして以下のように agentSystem
を更新します
override func update(_ currentTime: TimeInterval) {
let delta = prevTime == 0 ? 0 : currentTime - prevTime
prevTime = currentTime
agentSystem.update(deltaTime: delta)
}
prevTime はフィールドに必要なので追加しておきましょう
var prevTime: TimeInterval = 0
deltaTime は前回の更新からどれくらい経過したかを指定します
おそらくこの間隔が大きければ大きいほどエージェントの動きが大雑把になるんだと思います
今回は GameScene 側の update が呼ばれる度に agentSystem.update
もコールしているのでかなり細かくエージェントの動きを追従することができるようになります
動作確認
これで起動してみましょう
今回は特に SKSpriteNode などを配置していないのでコンソール画面で挙動を確認します
起動すると agent2 の座標が次々と流れていきます
よく見ると agent1 の座標 (0, 0)
に向かって移動しているのがわかると思います
最後に
GKAgent2D を使ってエージェントを動かしてみました
今回は追従するような動きでしたが他にも GKGoal にいろいろとメソッドが用意されている組み合わせることで複雑な動きもできると思います
今回検証していないですが気になった点としては
- スピードをどう調整するのか
- エージェントが移動する導線上に壁などを設置することはできるのか
あたりは気になりました
GKAgent2D は SKSpriteNode の世界とは別の世界になると思います
なので物理エンジンを使って衝突判定をする場合にはエージェント側の動きも衝突を考慮する必要があるのではと思いました
この辺りは細かい検証ができていないのでやってみないと何とも言えません
0 件のコメント:
コメントを投稿