●「Agents, Goals, and Behaviors」を利用したオブジェクトの移動 |
---|
続いて、サンプルの飛行機を「Agents, Goals, and Behaviors」を使って移動させるアプリを作ります。
まずはGameViewControllerのコードを最小限にします。GameViewController.swiftを下記のように修正してください。
import UIKit import QuartzCore import SceneKit class GameViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let scnView = view as? SCNView scnView?.delegate = self scnView?.isPlaying = true let scene = SCNScene(named: "art.scnassets/ship.scn") scnView?.scene = scene // 光源の設置 let lightNode = SCNNode() lightNode.light = SCNLight() lightNode.light?.type = .omni lightNode.position = SCNVector3(x: 0, y: 10, z: 10) scene?.rootNode.addChildNode(lightNode) let ambientLightNode = SCNNode() ambientLightNode.light = SCNLight() ambientLightNode.light?.type = .ambient ambientLightNode.light?.color = UIColor.darkGray scene?.rootNode.addChildNode(ambientLightNode) // 飛行機の角度調整 let ship = scene?.rootNode.childNode(withName: "ship", recursively: true) ship?.eulerAngles = SCNVector3(x: 0, y: Float.pi, z: 0) } override var prefersStatusBarHidden: Bool { return true } } extension GameViewController: SCNSceneRendererDelegate { // 1フレームごとに呼ばれるメソッド func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { print(time) } }
これで飛行機が配置されているだけの状態になりました。
次は、実際に「Agents, Goals, and Behaviors」を使って飛行機を移動させます。
まずはプロジェクト設定の下にあるボタンからGameplayKitを追加します。
続けてGameViewControllerを下記のように修正します。
import UIKit import QuartzCore import SceneKit import GameplayKit // 今回追加 class GameViewController: UIViewController { // 今回追加ここから let agentSystem = GKComponentSystem(componentClass: GKAgent3D.self) var prevTime: TimeInterval = 0 let shipAgent = GKAgent3D() // 今回追加ここまで override func viewDidLoad() { // 省略 // 飛行機の角度調整 let ship = scene?.rootNode.childNode(withName: "ship", recursively: true) ship?.eulerAngles = SCNVector3(x: 0, y: Float.pi, z: 0) // 今回追加ここから let targetAgent = GKAgent3D() targetAgent.position = float3(0, 0, -300) shipAgent.maxAcceleration = 1 shipAgent.maxSpeed = 1 shipAgent.delegate = self shipAgent.behavior = GKBehavior(goals: [ GKGoal(toSeekAgent: targetAgent), ]) agentSystem.addComponent(shipAgent) // 今回追加ここまで } override var prefersStatusBarHidden: Bool { return true } } // 省略
上記コードでは、飛行機のagent(shipAgent)が座標(x: 0, y: 0, z: -300)に向かうようなルールを作成しました。
次は、飛行機オブジェクトがそのルールに沿って移動する処理を追加します。
// 省略 extension GameViewController: SCNSceneRendererDelegate { // 1フレームごとに呼ばれるメソッド func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { // 今回追加ここから if prevTime == 0 { prevTime = time } agentSystem.update(deltaTime: time - prevTime) // 今回追加ここまで } } // 今回追加ここから extension GameViewController: GKAgentDelegate { func agentDidUpdate(_ agent: GKAgent) { if let ship = (view as? SCNView)?.scene?.rootNode.childNode(withName: "ship", recursively: true), let agent = agent as? GKAgent3D { ship.position = SCNVector3(agent.position) } } } // 今回追加ここまで
これで飛行機が奥に向かって移動するようになりました。
前項では、3Dゲームへの「Agents, Goals, and Behaviors」適用を行いました。実は2Dでも3Dでも実装の流れとしては、ほとんど同じです。
どちらも大きな流れとしては「エージェント(GKAgent)インスタンスを作成して、そこにルール(GKRule)を追加する」というものになります。
変更点としては、扱う位置情報が2次元から3次元になるだけなので、2Dゲームと大きな違いはなく実装できると思います。
最後に障害物を設置したときの動きも見ていきます。
鬼ごっこアプリ同様に、GKObstacleを使って障害物を設置します。GameViewControllerのviewDidLoadを下記のように修正してください。
class GameViewController: UIViewController { // 省略 override func viewDidLoad() { // 省略 let targetAgent = GKAgent3D() targetAgent.position = float3(0, 0, -300) shipAgent.maxAcceleration = 1 shipAgent.maxSpeed = 1 shipAgent.delegate = self // 今回修正ここから let obstacle = GKSphereObstacle(radius: 100) obstacle.position = vector_float3(0, 0, -150) shipAgent.behavior = GKBehavior(goals: [ GKGoal(toSeekAgent: targetAgent), GKGoal(toAvoid: [obstacle], maxPredictionTime: 100.0) ], andWeights: [NSNumber(value: 1), NSNumber(value: 50)]) // 今回修正ここまで agentSystem.addComponent(shipAgent) } // 省略 }
今回追加したGKSphereObstacleは3Dゲーム用の障害物オブジェクトです。この障害物を避けるルール【GKGoal(toAvoid: [obstacle], maxPredictionTime: 100.0)】を追加することで、飛行機が斜めに移動するようになりました。
以上で、3Dゲームにおける「Agents, Goals, and Behaviors」の基本的な使い方は終了です。
今回のソースはkonkai.zipからダウンロードできます。
これまで4回にわたって「Agents, Goals, and Behaviors」の使い方を見てきましたがいかがでしょうか? GameplayKitは分かりにくいところもありますが、うまく使えば開発工数を大いに削減できます。
もし機会がありましたら、本連載を参考に試していただけると幸いです。
田町のベンチャーで働くエンジニア。
仕事ではiPhoneアプリの開発やRailsを使ったWebサービス開発を行っている。最近のマイブームはUnityを使った3Dゲーム開発。
Copyright © ITmedia, Inc. All Rights Reserved.