モバイルゲームアプリケーション開発を学ぶにあたり、Xcode のゲームテンプレートが作成する UIKit ベースのプロジェクトではなく、現在主流の SwiftUI ベースのプロジェクトで開発を始めたかったため、調べてみました。
iOS 14以降の実装
学習を目的としたため、調べた中で最もミニマムな実装をしている次のサイトを参考にしました。
iOS の App テンプレートで、インターフェースに SwiftUI、プログラミング言語に Swift を選択したプロジェクトを作成します。
プロジェクトへ GameScene.swift という名前の Swift File を追加します。GameScene.swift を次の内容へ書き換えます。
import SpriteKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
// something
}
}
既存の ContentView.swift ファイルを次の内容へ書き換えます。
import SwiftUI
// [1] SpriteKit をインポートします。
import SpriteKit
struct ContentView: View {
// [2] GameScene を初期化し、変数へ格納します。
var scene: SKScene {
let scene = GameScene()
scene.scaleMode = .resizeFill
return scene
}
var body: some View {
// [3] SpriteView をレンダリングします。
SpriteView(scene: self.scene)
.ignoresSafeArea()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
iOS 13以前の実装
SKView は UIKit の UIView であるため、UIViewRepresentable プロトコルを採用するコンテナを作成することで SwiftUI のビュー階層へ統合できるようです。
UIViewRepresentable プロトコルは、公式リファレンスを参照しました。
SKView を UIViewRepresentable プロトコルでラップする例は、次のサイトを参考にしました。
最もミニマルな実装のプロジェクトへ SKViewContainer.swift という名前の SwiftUI View を追加します。SKViewContainer.swift を次の内容へ書き換えます。
import SwiftUI
import SpriteKit
struct SKViewContainer: UIViewRepresentable {
typealias UIViewType = SKView
var skScene: SKScene!
init(scene: SKScene) {
skScene = scene
// 必要に応じて書き換えます。
self.skScene.scaleMode = .resizeFill
}
func makeUIView(context: Context) -> SKView {
let view = SKView(frame: .zero)
// デバッグのためのコードです。
view.showsFPS = true
view.showsNodeCount = true
return view
}
func updateUIView(_ view: SKView, context: Context) {
view.presentScene(context.coordinator.scene)
}
class Coordinator: NSObject {
var scene: SKScene?
}
func makeCoordinator() -> Coordinator {
let coordinator = Coordinator()
coordinator.scene = self.skScene
return coordinator
}
}
struct SKViewContainer_Previews: PreviewProvider {
static var previews: some View {
// プレビューは表示できません。
SKViewContainer(scene: SKScene())
}
}
既存の ContentView.swift ファイルを次の内容へ書き換えます。
import SwiftUI
struct ContentView: View {
var body: some View {
SKViewContainer(scene: GameScene())
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}