はじめに
先日かわいいチキンを作ったのですがどうせなら AR で表示したいという欲が出てきました
SpriteKitで2D横スクロールゲームをつくろう(その1)
調べていると ARSKView というまさに AR でチキンを表示するために用意されたような View を発見しました。
これはもうやるしかない!ということで AR でチキンを表示します。
完成形はこんな感じです
やりたいこと
やりたいことは下記。
- 画像マーカーを認識する
- 認識した画像マーカーにチキンを表示する
画像マーカー設定
下記記事を参考に画像マーカーを設定します。
- Assets > AR and Textures > New AR Resource Group で Group 追加
- マーカー用の画像を追加
- マーカーのサイズ指定(今回はてきとーに 15cm * 15cm で設定しました)
マーカーにはちょうど手元にあったオレイカルコスの結界を使います(なんか警告出てますが気にしません)。
これでマーカーの設定は終わりです。
ARSKViewを表示する
とりあえず ARSKView
を表示してみます。
- info.plist に「Privacy - Camera Usage Description」を追加
- Storyboard で
ViewController
にARSKView
を追加 -
ViewController
にARSKView
を接続 -
ViewController
に下記追加import UIKit import ARKit final class ViewController: UIViewController { @IBOutlet private weak var arskView: ARSKView! override func viewDidLoad() { super.viewDidLoad() arskView.presentScene(.init(size: arskView.frame.size)) let configuration = ARWorldTrackingConfiguration() arskView.session.run(configuration) } }
これで動きます!(カメラ映るだけですが)
マーカーを認識させる
次にマーカーを認識できるようにしていきます。
以下のように ARWorldTrackingConfiguration
から ARImageTrackingConfiguration
に変更し ARSKViewDelegate
を追加します。
arskView.delegate = self
let configuration = ARImageTrackingConfiguration()
let images = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil)
configuration.trackingImages = images!
configuration.maximumNumberOfTrackedImages = 1
arskView.session.run(configuration)
extension ViewController: ARSKViewDelegate {
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
print("マーカーみっけ!!!")
return nil
}
}
これでマーカーを認識するとコンソールに「マーカーみっけ!!!」と表示されるようになりました。
チキンを表示する
いよいよチキンを表示します。
ARSKViewDelegate
の部分を下記のように修正します。
extension ViewController: ARSKViewDelegate {
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
let parentNode = SKNode()
let chicken = SKSpriteNode(texture: .init(imageNamed: "c1"), size: .init(width: 32, height: 32))
let jumpTextures: [SKTexture] = [
.init(imageNamed: "j1"),
.init(imageNamed: "j2")
]
let action = SKAction.group([
.animate(with: jumpTextures, timePerFrame: 0.2),
.sequence([
.wait(forDuration: 0.2),
.moveBy(x: 0, y: 10, duration: 0.2),
.moveBy(x: 0, y: -10, duration: 0.2)
])
])
chicken.run(.repeatForever(action))
parentNode.addChild(chicken)
return parentNode
}
}
view(_ view: ARSKView, nodeFor anchor: ARAnchor)
で SKNode
を返すと指定の ARAnchor
にノードが追加されるのでこれでチキンが表示できます。
parentNode
に chicken
を add しているのはそのまま chicken
を返すと ARAnchor
で固定されてしまいアニメーションで動かせないためです。
参考:ARKitでつくったAR空間上に置いたSpriteKitのSKNodeをアニメーションで動かす方法
おわりに
意外とかんたんに AR でかわいいチキンの表示ができました
50 行いかないくらいでサクッと AR が試せます!いい時代ですね
ソース全体
import UIKit
import ARKit
final class ViewController: UIViewController {
@IBOutlet private weak var arskView: ARSKView!
private let jumpTextures: [SKTexture] = [
.init(imageNamed: "j1"),
.init(imageNamed: "j2"),
]
override func viewDidLoad() {
super.viewDidLoad()
arskView.delegate = self
arskView.presentScene(.init(size: arskView.frame.size))
let configuration = ARImageTrackingConfiguration()
let images = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil)
configuration.trackingImages = images!
configuration.maximumNumberOfTrackedImages = 2
arskView.session.run(configuration)
}
}
extension ViewController: ARSKViewDelegate {
func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
let parentNode = SKNode()
let player = SKSpriteNode(texture: .init(imageNamed: "c1"), size: .init(width: 32, height: 32))
let action = SKAction.group([
.animate(with: jumpTextures, timePerFrame: 0.2),
.sequence([
.wait(forDuration: 0.2),
.moveBy(x: 0, y: 10, duration: 0.2),
.moveBy(x: 0, y: -10, duration: 0.2)
])
])
player.run(.repeatForever(action))
parentNode.addChild(player)
return parentNode
}
}