こんにちは!VR元年が終わり、2017年となりました!
2016年12月にはOculus Touchも無事発売され、今回から、公式のSDKを参照しながら解説が書けるようになりました!
今回のソースコード
今回は、前回使用したレポジトリをcloneした後にの「vol2-avatar-sample」というブランチをcheckoutするか、こちらからzipでdownloadしてください。
本プロジェクトには
及び
が必要なので、この2つもダウンロードの上プロジェクトにインポートしてください。
また、開発した環境はUnity5.4.1f1ですが、5.4系であればおおむね問題なく動くようです。
Oculus SDKにTouchの要素が加わりました
最新のOculus SDKをダウンロードして確認してみると、TrackingSpaceの下に「LeftHandAnchor」と「RightHandAnchor」が確認できます。
Oculus Touchを作動させた状態でこの2つのオブジェクトを見ると、Touchコントローラーのポジションとローテーションが取得できていることがわかります。
逆に言えば、これだけです。
ボタンインプットの情報も取得できるため、この情報をもとに前回までのサンプルを組み立てることもできます。
今回はせっかくなのでOculus公式から提供されている、便利なツール「Oculus Avator SDK」を使ってみましょう。
Oculus Avatar SDKを触ってみる
Oculusから提供されている、Oculus Avatar SDK。
これは何かというと、Oculus Homeで設定できる「Oculus Avatar」の仕組みをそのまま自分で作るVRアプリで利用できてしまうSDKです。
OC3でも話題になった、このOculusの新しいアバターがもう使えちゃうんです!素晴らしいですね。
冒頭で書いたとおり、Oculus公式からダウンロードできます。
パッケージ内には4つのサンプルシーンが入っています。
サンプルシーンでできることを1つ1つ見ていきましょう。
1. Controllersシーン
コントローラーを表示するサンプルです。Oculus Avatarでは、プレイヤー自身の姿はTouchコントローラーによる表示部分しか見えません。それを確認できるのがこのシーンです。シーンを実行すると手とコントローラーの表示を確認できますがが、こちらを手のみの表示にすることもできます。
手のみの表示にしたい場合はOvrAvatarコンポーネントの「Start With Controllers」をオフにします。
手のみの場合とそうでない場合では、グリップした時やボタンに手を置いた時の動きが微妙に変わりますので注意しましょう。(Gif画像は、いずれも「グリップトリガーボタンを押す」の操作です)
2. GripPosesシーン
このシーンは、普通に実行すると手が表示されるのみ。しかも、Touchを操作しても手が動かないので何じゃらほいと思う方もいるかもしれませんが、これは「デフォルトではできないポーズを指定する機能」のサンプルシーンとなります。
このシーンで表示される「パー」のポーズですが、実はOculusAvatarのCustom Poseで指定されています。
試しにこのCustom Poseをnullにした状態で実行してみると、通常通りコントロールできる手になります。
つまり、何かのイベントで任意の手のポーズにさせたい場合は、このシーンで指定されている通りにCustom Poseに特定のポーズを放り込めばいいということです。
グワシ!
3. LocalAvatarシーン
このシーンは、実行すると小さい自分のアバターが表示されていることが確認できます。
Oculus Homeで鏡合わせの自分を見ながらアクセサリを決めるシーンのように、自分の姿を外側から確認するための実装方法をこのシーンから知ることができます。
構成を見ると、LittlePedestalの下に「LittleAvatar」というオブジェクトが確認できます。
こちら、LocalAvatarとコンポーネントや階層構造が全く同じです。唯一違うのは、「Show First Person/Third Person」のチェックです。
つまり、LocalAvatarを複製してThirdPersonにチェックするだけで自分のアバターはバンバンコピーできちゃうということですね。
ためしにLocalAvatarを複製して、MediumPedestalに入れるとこうなります。
4. RemoteLoopbackシーン
このシーンを実行すると、自分の動きと全く同じような動きをするアバターが正面に見えるのが確認できます。
おや?LocalAvatarシーンと一緒かな?と思いきや、シーン構成を見ると「LocalAvatar」に加えて「RemoteAvatar」というのがあります。コンポーネントも「Ovr Avatar Remote Driver」というのがついてるようです。
このシーンで何が行われているかというのは、Remote Loopback Managerのスクリプトを見るとわかります。
まず、LocalAvatarのPacketRecordのdelegateに設定されているメソッドで、「SendPacketData」というメソッドが実行されています。
SendPacketDataでは、即「RecievePacketData」が実行されています。SendなのにいきなりRecieveって何やねんと思っちゃいますが、これは、「LocalAvatarがSendしたDataを」「LoopBackAvatarがRecieveする」という意味です。
というか、そういう処理が書いてあります。
つまり、このサンプルではLocalAvatarの動きのデータをPacketという形で送り出し、それを目の前にあるRemoteAvatarが即受け取ることで同じ動きを表現している、ということになります。
なんでそんなことを、LocalAvatarの方が早いのではないか、と思うかもしれませんが、この仕組みは次に解説する通信の仕組みを実装する時に使えます。
Avatar同士で通信してみる
RemoteLoopbackシーンは1プレイヤーの動きのデータをパケットで送り、もう1つのアバターに同じ動きをさせるというサンプルでした。
ということは、パケットの送り先/もらい先をHost/Clientに分ければ通信が成立することになりますね。
ではやってみましょう。
・・・というわけで、こちらに通信が成功したサンプルがございます。
基本的には前回まで使っていたUNET周りの実装を流用します。
違うのは、Spawnするネットワークオブジェクトが今回はOculus Avatarを使ったものになるという点です。
このネットワークオブジェクトのためのコード「SimpleNetworkAvatar.cs」にパケットのやりとりが記述されています。
注目すべきは、以下 に引用するコードです。
「hasAuthority」が有効という条件の場合にのみ、OnLocalAvatarPacketRecordedというメソッドがdelegateに指定されています。
OnLocalAvatarPacketRecordのメソッドでは、取得したPacketをoutputStreamに書き込み、SendPacketDataというメソッドに渡しています。
さらにSendPacketDataのメソッドでは、Clientの場合はCommandアトリビュート、Hostの場合はClientRpcアトリビュートを用い、いずれの場合でもAutorityを持たない側でm_RemortDriver.QueuePacketのメソッドにinputStreamが渡されます。これで、Authorityを持つAvatarの動きがAuthorityのないAvatarの動きに反映されるということになります。
このようにして、実際にAvatar同士で通信している様子がこちらです。
https://www.youtube.com/watch?v=XP2nYrQgOjs
こちらの映像はビルドしたアプリをキャプチャしたものですが、1点注意する必要があります。
Oculus Avatarは、ビルドされたアプリ上だとデフォルト状態で描画されません。これを解決するためには、以下の2点を設定した上でビルドしてください。
・Edit > Project Settings > Graphicsの設定項目の1つ、「Always Included Shaders」のSizeを3つ増やし、Project内のOvrAvatar > Content > Materials にあるAvatarSurfaceShader、
AvatarSurfaceShaderSelfOccluding、AvatarSurfaceShaderPBSを新たな3項目に設定する
・Build SettingのArchitectureをx86_64に設定する
いかがでしたでしょうか?
こんなに簡単にAvatarが利用できるなんて、Oculusさんは毎度のこと太っ腹すぎます!
さて、次回はこのOculus Avatarを使ったさらなる応用例を解説していきます。
お楽しみに!