U1チップによる空間認識 - Nearby Interaction Framework
iOS 14で新たに追加されたNearby Interactionは、U1チップを搭載したiPhone同士でインタラクションを行うためのフレームワーク。
インタラクションを行う、と言われてもピンとこないかもしれないが、U1は「空間認識」を行えるチップなので、それにより互いに相手の距離と方向がわかる。で、その情報を使って相互になんかしましょうというもの。
以下、WWDC 2020のセッション、"Meet Nearby Interaction"を見たメモ。
2020年6月時点での対応端末
iPhone 11シリーズに加え、LiDARを搭載する新型iPad ProはU1チップも搭載しているかと適当に考えていたが、非搭載。つまり今のところ対応端末はiPhone 11系のみ。
シミュレータでも動作確認可能
そんなわけでNearby Interactionを実機で試すには最低でも2台のiPhone 11が必要で、個人ではなかなかその状況を用意するのは難しい。
それを見越してか、Nearby Intearactionはシミュレータでも動作する。
ただし、画面上ではあくまで2次元なので、「空間認識」の醍醐味である3次元的なインタラクションを体感するにはやはり実機で試したいところ...
最小実装
インタラクション開始にあたってどんなやりとりが必要なのか、何ができるのか、どんな情報が得られるのか、という大枠を理解するにはソースコードを見たほうが理解が早い。
サポートしているかの確認
guard NISession.isSupported else {
print("Nearby Interaction is not available on this device.")
return
}
セッションオブジェクトの作成
niSession = NISession()
niSession?.delegate = self
delegateプロパティにセットするオブジェクトはNISessionDelegateプロトコルに準拠している必要がある(が、すべてのメソッドがoptionalなので実装がなくても動作はする)
ディスカバリトークンを生成し、交換する
guard let myToken = niSession?.discoveryToken else { return }
if let encodedToken = try? NSKeyedArchiver.archivedData(withRootObject: myToken, requiringSecureCoding: true) {
<# share token using your app's networking layer #>
}
ここはちょっと解説が必要だと思うので、WWDC 2020のセッションより該当箇所を抜粋する:
抜粋が長くなってしまったが、インタラクションする相手を識別する手段として「ディスカバリトークン」(クラスとしてはNIDiscoveryToken)なるセッションごとに一時的に生成するトークンを交換しあう、という話。
で、このトークンを交換する部分、上のコードでは`<# share token using your app's networking layer #>`とプレースホルダーで表記されているが、どういうことかというと、このディスカバリ・トークンの交換のための通信はNearby Interactionフレームワークでは面倒をみない。ちなみにサンプルコードではMultipeerConnectivityフレームワークを使用している。
・・・というかこのへんで気付いたが、そもそもNearby Interactionフレームワークでは通信(データの交換)は行わない。あくまでU1の空間認識で互いの位置・方角がわかるよ、通信は別でやってね、という設計のようだ。
受け取ったトークンをデコード
guard let peerDiscoveryToken = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NIDiscoveryToken.self, from: peerTokenData) else {
print("Unexpectedly failed to decode discovery token.")
return
}
NINearbyPeerConfigurationオブジェクトを作成
デコードした相手のNIDiscoveryTokenオブジェクトをイニシャライザの引数に渡してNINearbyPeerConfigurationを初期化する。
let config = NINearbyPeerConfiguration(peerToken: peerDiscoveryToken)
### セッション開始
NISessionのrunメソッドの引数にNINearbyPeerConfigurationオブジェクトを渡してセッションを開始する。
niSession?.run(config)
以上が最小実装。
NISessionDelegateの実装
前述の最小実装によりNearby Interactionのセッションを開始できたとはいえ、アプリケーションとして何の機能もない。実際のインタラクションを実装するには、NISessionDelegateプロトコルに定義されているデリゲートメソッド群に実装を与えていく必要がある。
まず、近接オブジェクトに更新があると呼ばれるのが下記メソッド:
func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObject])
nearbyObjects引数よりNINearbyObjectオブジェクトの配列が得られる。
1台のiPhoneは複数のセッションを同時に張れるため、特定のpeerのNINearbyObjectオブジェクトを取り出すには次のようにディスカバリトークンを見る。
// Find the right peer.
let peerObj = nearbyObjects.first { (obj) -> Bool in
return obj.discoveryToken == peerToken
}
guard let nearbyObjectUpdate = peerObj else {
return
}
NINearbyObject
NINearbyObjectクラスは次のようにdistanceプロパティから距離を、directionプロパティから3次元の方向を得られる。
extension NINearbyObject {
public var distance: Float? { get }
public var direction: simd_float3? { get }
}
ARKitとの併用は可能か?
空間を正しく認識すると聞いて思いつくのがARKitと組み合わせることだが、実装を見る限りARKitとバッティングするような部分はないので、併用は可能だと思われる(実機が手元に2台ないので試せてない)
バックグラウンドでも動作するか?
WWDCセッションでの次の言及から、フォアグラウンドでのみ動作すると思われる:
ここから先は
#WWDC2020 の勉強メモ
堤がWWDC 2020およびiOS 14についてセッションやサンプルを見つつ勉強したことを記事にしていくマガジンです。NDAの都合上、Ap…
最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/