概要
ARKitアドベントカレンダー2018 2日目は @kaoryuuu がお送りします!
今回はネイティブアプリでARKitでの開発してきた際に必要そうな内容を紹介したいと思います。
はじめに
ARKit、触ったことある方いますでしょうか。「興味はあるけど難しそう」と印象を持っている方は多いと思います。
個人的な主観ですが、ARKit自体はそこまで難しいものではありません。3DモデルをAR空間上に表示させたりするだけなら多分1日も要らないです。ただ、 ARをユーザー体験として落とし込むのは非常に難しいと自分は思っております。
Appleのサンプルアプリやドキュメントを使いながら、良いアプリつくるための知見を共有していきます。
ARKitの基礎を知りたい
(宣伝)こちらを参考にしていただけるとざっくりどのようなものか掴めるかと思います。
ARKitを扱う際の心構えとTips
以前、チートシート的な物も作成したので参考にしていただけると幸いです。
サンプルコードから学ぶ
ARKitでの開発にはApple公式のサンプルを参考にするとだいたいやりたいことが載っています。
自分がつくりたいものに合わせて見てみると良いかと思います。
https://developer.apple.com/documentation/arkit
・ Building Your First AR Experience
・ Creating a Persistent AR Experience
・ Handling 3D Interaction and UI Controls in Augmented Reality
複数人でARやりたい!
・Creating a Multiuser AR Experience
ネイティブでゲーム作りたい!
ゲームだったらUnityの方が正直楽だと思います。。。が一応。
・ SwiftShot: Creating a Game for Augmented Reality
ARKitと何か組み合わせてみたい
・ ARKit+Vision
こちらのプロジェクトでは実際にMLモデルを読み込んでAR空間上に認識したラベルを表示するものが公開されております
https://github.com/hanleyweng/CoreML-in-ARKit
すでに学習済みのCore MLのデータもAppleが提供しているのでまずはこれを使ってみるとよいでしょう
https://developer.apple.com/jp/machine-learning/build-run-models/
・ARKit+Core Location
・Creating an Immersive AR Experience with Audio
・Adding Realistic Reflections to an AR Experience
Haptic Feedback
UIFeedbackGenerator
ブルっと端末が震えるやつです。
アプリインストール時などに「ピコーン」と鳴ると同時に少し振動するのが気持ち良いですよね(?)
ARを扱う上でHaptic Feedbackは非常に良い働きをしてくれます。
AR上でのオブジェクトの配置やタップ判定などに、「あ、今このオブジェクトを触っているんだ」感をユーザーに伝える手段として活用できます。
参考:https://techblog.zozo.com/entry/ios_ui_feedbcak_generator
ARTrackingState
現在カメラに写っているフレームから、トラッキングの状態を取得することができます
NotAvailable
Camera position tracking is not available.
トラッキングが利用できない状態。
(例えば、カメラが何かに覆われて映し出されている画面が真っ黒になっているとか)
Limited(ARCamera.TrackingState.Reason)
Tracking is available, but the quality of results is questionable.
利用できるけど結果は微妙かも。。
また、その理由も取得できます。(後述参照)
Normal
Camera position tracking is providing optimal results.
ARCamera.TrackingState.Reason
どんなエラーなのか、例えばInsufficientFeaturesは画面に映し出されている特徴量が少ないという理由になっています。iOS12のMeasureアプリでは特徴点が少なかった際に画面全体に端末を動かすようアニメーションをオーバーレイさせています。
public enum Reason {
/** Tracking is limited due to initialization in progress. */
case initializing
/** Tracking is limited due to a excessive motion of the camera. */
case excessiveMotion
/** Tracking is limited due to a lack of features visible to the camera. */
case insufficientFeatures
/** Tracking is limited due to a relocalization in progress. */
@available(iOS 11.3, *)
case relocalizing
}
使い所 ~UseCase~
公式アプリでもトラッキングの状態が悪いと正しく認識させるように促すようなアニメーションを表示させたり、
注意が促されていますね。
extension ViewController: ARSCNViewDelegate {
// カメラのトラッキング状態が変わった際に呼ばれる
func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
statusViewController.showTrackingQualityInfo(for: camera.trackingState, autoHide: true)
switch camera.trackingState {
case .notAvailable, .limited:
// ここで何かしらの情報を出したり、動作を制限させてあげる
case .normal:
// 正常
}
}
ARAnchor
name
iOS12からARAnchorにnameを付与できるようになりました
let anchor = ARAnchor(name: "hoge", transform: float4x4)
※Anchorは文字のごとく、位置を固定化させるようなイメージです。
位置を変えたい場合は直接Anchorの座標を変更するのではなく、NodeのPositionを変更するなどしたほうが良いです。
使い所 ~UseCase~
func setObject() {
// 任意の場所に何か表示させたい
let anchor = ARAnchor(name: "hoge", transform: float4x4)
sceneView.session.add(anchor: anchor)
}
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let anchorType = AnchorType(name: "hoge") else {
return
}
// 追加されたものがhogeAnchorの場合だけ処理させたい
}
SCNNode
CategoryBitMask
詳しい内容は記事はこちらの記事がわかりやすいです。
SceneKitにおける物体衝突検知を理解する
HitTest時のOptionに設定することで特定のBitMaskに対応したものだけを認識させることができます。
TimingModeでEasing
https://developer.apple.com/documentation/scenekit/scnactiontimingmode
アニメーションにEasingをつけることも可能です
let foo = SCNAction()
foo.timingMode = .easeIn //linear, easeOut, easeInEaseOut
オブジェクトをカメラの方向に向ける
let constraint = SCNBillboardConstraint()
constraint.freeAxes = SCNBillboardAxis.Y
constraints = [constraint]
最後に
何か間違い等ありましたらコメントをいただけると幸いです!