【GameplayKit】ゲームを効率的につくるためのフレームワーク①


この記事について

iOSアプリでゲームを作成するには、Unityが主流のようですがAppleもいろいろ頑張っているようでXcodeにもGameplayKitなるフレームワークが追加され強化されているようです。
どのようなものか、どうやって使うのか知りたいのですが、小生のような凡人が理解できるレベルの情報があまりないようなので調査しました。
内容はほとんど、Appleのデベロッパサイト及びサンプルコードを適当に翻訳・解説したものになります。誤った部分などお気付きの点は、遠慮なくご指摘お願いします。
なお、SceneKitの基本的な使い方はこちらの記事・Xcodeの基本的な使い方はこちら(iBooksで見る)をどうぞ。

GameplayKit

まず、実装できる機能について7つの目的が挙げられています。
1. Randomization
2. Entities and Components
3. State Machines
4. The Minmax Strategist
5. Pathfinding
6. Agent, Goals, and Behaviors
7. Rule Systems

解説するサンプルコード

AppleデベロッパサイトにBoxes: GameplayKit Entity- Component Basicsなるサンプルプロジェクトがあったので、調べました。プロジェクトにはmacやappleTV向けのコードもありましたが、ここではiOSに限って調べました。
このサンプルは、Entities and Componentsの理解を目的としているようです。


サンプルは「画面をタップするとブロックが跳ねる」ゲームです。ご覧の通り、SceneKitの3D機能も使っているようですが、果たしてここにGameplayKitがどこでどんなふうに実装されているのかを追って調べていきたいと思います。

主なクラス

このサンプルプロジェクトでは、GameplayKitフレームワークにある以下のクラスを扱っています。

GKEntityクラス

ゲーム画面にある5色のボックスは、GKEntityオブジェクト。

GKComponentクラス

このクラスのインスタンス(コンポーネント)が、ボックスに与えるべき機能をまとめる。
まとめられる機能によって、インスタンスがいくつか定義してある。それぞれのボックスが実装するコンポーネントを組み合わされることで、ボックスが特徴づけられる。

  • GeometryComponent(全てのボックスが実装)
  • ParticleComponent(黄色と青のボックスが実装)
  • PlayerControlComponent(緑と青のボックスが実装)

GKComponentSystemクラス

サンプルプロジェクトの解説

Game.swift

シーンのクラスファイル。setUpEntities()メソッドで、エンティティに各種コンポーネントを実装している。

GeometryComponent.swift

全てのボックスが実装するコンポーネント。SceneKitのオブジェクトに物理的な挙動などを設定する。

ParticleComponent.swift

このコンポーネントを実装したボックスは、炎とスパークのパーティクル(粒子の演出)を表示する。

PlayerControlComponent.swift

このコンポーネントを実装したボックスは、プレイヤーがアプリに対してインタラクション(iOSなら画面タップ)するたびに跳ね上がる。

再現手順

大まかな流れは以下の通りです。
1. プロジェクト作成
2. シーンファイル作成
3. フロアオブジェクトを配置
4. ブロックオブジェクトを配置
5. 照明オブジェクトを配置
6. カメラオブジェクトを配置
7. Gameクラスを定義

プロジェクト作成

シングルビューテンプレートを選択する。
ファイル名を変更(ViewController.swift => GameViewController.swift)する。
ビューコントローラのIdentity Inspectorの設定を変更する。

  • クラスファイルをGameViewControllerクラスに変更
  • ルートビューをSCNViewクラスに変更

シーンファイル作成

SceneKit Scene Fileを新規作成(GameScene.scn)

フロアオブジェクトを配置

オブジェクトライブラリから、Floorを配置する。
インスペクタエリアの設定を以下のように変更する。

  • Physics Type: Static
  • Diffuse: Black
  • ambient: Black

ブロックオブジェクトを配置

シーンファイルを表示する。
オブジェクトライブラリから、Boxを5つ(redBox, yellowBox, greenBox, blueBox, purpleBox)配置しする。
Material Inspectorから色(Diffuse)を変更する。
Physics Inspectorで、PhysicsTypeをDynamicに変更する。
全てのブロックSizeは、Width, Height, Length を1に設定
Position(x, y, z)は以下のとおり。

  • redBox (x:-4, y: 0.5, z:0)
  • yellowBox (x:-2, y: 0.5, z:0)
  • greenBox (x: 0, y: 0.5, z:0)
  • blueBox (x: 2, y: 0.5, z:0)
  • purpleBox (x: 4, y: 0.5, z:0)

照明オブジェクトを配置

オブジェクトライブラリから、Ambient lightとDiractional lightを一つずつ配置する。
Node Inspectorからそれぞれのライトのオイラー角と位置を設定する。

  • ambient
    • Position(x:0, y:12, z:0)
    • Euler (x:0, y:0, z:0)
  • directional
    • Position(x:10, y:10, z:10)
    • Euler (x:-45, y:0, z:45)

カメラオブジェクトを配置

オブジェクトライブラリから、Cameraを配置する。
Node Inspectorから位置とオイラー角を設定する。

  • Position(x:0, y:3, z:10)
  • Euler (x:0, y:0, z:0)

Attribute Inspectorから画角Projection(Xfov:0°, Yfov:45°)を設定する。

Gameクラスを定義

Cocoa Touch ClassテンプレートからNSObjectのサブクラスを新規作成する。(Game.swift)
Gameクラスを定義する。

Game.swift
import SceneKit

class Game: NSObject, SCNSceneRendererDelegate {
    let scene = SCNScene(named: "GameScene.scn")!
}

ビューコントローラにシーンを表示

GameViewController.swift
import UIKit
import SceneKit

class GameViewController: UIViewController {
    let game = Game()

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let scnView = view as? SCNView else { fatalError("Unexpected view class") }

        scnView.backgroundColor = UIColor.lightGray
        scnView.scene = game.scene        
    }
}

ビルド

いったん、シーンが正しく表示されるかを確認しておきましょう。

続く

長くなってきたので、続きは別記事にすることにします。
ゲームを効率的につくるためのフレームワーク②
各種コンポーネントを定義して、任意のエンティティに実装していきます。