（2017/4/26 追記修正）Google Cardboard SDK for Unity v0.6の３Dサウンド  (Spatial Audio)と視線マーカー

# はじめに
1/13に[Google Cardboard SDK for Unity](https://github.com/googlesamples/cardboard-unity/commits/master)が0.6になりました。大きな変更は**3Dオーディオ Spatial Audio**（[公式ブログ](http://googledevelopers.blogspot.jp/2016/01/spatial-audio-comes-to-cardboard-sdk.html))ですが、ほかにもVR用の視線マーカーが変更になってますね。VRアプリでよく見られるような、「近くのオブジェクトに視線マーカーをあわせると、マーカーが近くに寄って大きくなる」という動作がスムーズになっています。

そこで、この辺の新しい使い方をわかる範囲で整理してみます。新しい情報が入ったら、適宜アップデートするつもりです。

**追記：以下、３Dオーディオについて、GVR Unity SDK v1.40.0で変更になっている部分を修正、追記しました（2017/4/26）。**



# １．３Dオーディオ Spatial Audioの使い方

## Google Cardboard SDKの３Dオーディオの特徴

Unityで使える、無料のVRアプリ用の３Dオーディオとしては、すでにOculus Audio SDKがありますが（[紹介記事](http://qiita.com/yanosen_jp/items/03de6ad02a05493f343b))、それとCardboard SDKではだいぶ使い方が違います。

Oculus Audio SDKでは音源はすべて「点」として考えて、音が周囲に一様に広がると仮定するのに対し、Cardboard SDKでは以下に示すようにDirectivity（音の方向性）の設定が可能です。また、Oculus Audio SDKではAudio mixerでシーン全体に対して反響などの音響環境を設定した（最新のSDKでは、シーンの一部に対して設定可能）のに対して、Cardboard SDKではAudio Roomという形で、シーン内の決められたエリアに限定した形で音響環境を設定できます。これらはかなり便利な機能ですが、その分、３Dオーディオの設定も複雑になっています。

（2017/4/26 追記修正）Googleのサイトのほうに、[Spatial Audioに関する英語の解説](https://developers.google.com/vr/concepts/spatial-audio)が掲載されているので参考にしてください。また、Spatial Audioのサンプルは、[GVR SDKのレポジトリ](https://github.com/googlevr/gvr-unity-sdk)をクローンし、Samples/SpatialAudioフォルダにあるプロジェクトを開いてください。


## Editorの設定

Cardboard SDKで３Dオーディオを利用するには、まずEditorでProject Settings/Audioの中のSpatializer PluginをCardboardAudio Spatializerに設定します。

![AudioSpatilizer.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/ea3480ec-e059-31fb-3401-49b7ec2a97d2.png)


忘れやすいので、注意しましょう！

## 音源の設定

次に、音源になるオブジェクト（この場合はCube)にCardboard/Scripts/AudioフォルダにあるCardboardAudioSource.csをアタッチします。

![AudioSource.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/dc2d6132-0d6e-639b-91be-6af29c128208.png)

ここで、3Dオーディオに関してはVolume　2つのパラメータを設定できます。

* Volume Rolloff: どの距離で音が聞こえるかを設定します。[UnityのVolume Rolloffの設定](http://docs.unity3d.com/ja/current/Manual/class-AudioSource.html)に準拠しているので、そちらをご覧ください。

* Directivity: 音の方向性を決められます。 右に表示される極座標グラフは、以下の計算式に基づいています。

`float r = Mathf.Pow(Mathf.Abs((1 - alpha) + alpha * Mathf.Cos(theta)), order)`

ここで、rは半径（距離）、thetaは角度を表します。この式によれば、alphaは角度成分の程度の強さ（つまり、広がり方の形）、orderは方向性の強さ（値が大きいほど、指向性が高く、広がりが少ない）となることがわかります。

パラメーターでの組み合わせの例をいくつか示しておきます。

![Directivity01.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/6f7a3146-bb95-3f70-4e54-6fceed99db75.png)

![Directivity0_5__1.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/9f746ecb-53af-33a3-45c8-168eea0316e6.png)

![Directivity0_5__10.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/30efc9d3-6a67-820d-c2d5-cbd3ebbd7089.png)

![Directivity11.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/42c86ff3-914d-f451-3f07-dcaac7194c60.png)



次に、HierarchyのCardboardMain/Head/MainCameraにCardboard Audio Listenerがアタッチされており、有効化（チェックが入っている）されていることを確認してください。

![Listener.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/34422fac-d07c-4a4b-84a8-4b377ce5938b.png)

これで、オブジェクトとCardboard Cameraの相対位置により、音が変化することがわかるはずです。

## 音響環境の設定

音は、周囲の周りの壁や床などので反射することで、色々と変化します。その、周囲の影響を設定します。

音響環境の設定は、Cardboard/Scripts/AudioフォルダにあるCardboardAudioRoom.csで行います。このスクリプトを、部屋に相当するゲームオブジェクトにアタッチしてください。ここでは、テキトウにDirectional Lightにアタッチしました。

![room.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/793f9707-18d9-4946-119f-f845f106915e.png)


すると、アタッチしたゲームオブジェクトの周囲に黄色い囲みが表示されます。音響環境の設定は、この中にAudioListenerがあるときのみ有効になります。この囲みの大きさはCardboardAudioRoom.csのsizeパラメータで変更できます。Sizeの設定は反射・反響の性質にも影響するので、部屋のサイズに合わせて正確に設定しましょう。

CardboardAudioRoom.csには、ほかにも上下左右前後の壁の材質の設定（Surface materials）, 反射の程度の設定（Reflectivity）, 反響の程度の設定(Reverb properties)が可能です。

### Reflectivity (反射)

Reflectivityは０～２まで設定できますが、０にすると、「フラット」な感じ、つまり音源からの直接音だけが聞こえます。Reflectivityを大きくすると、音源からの直接音に加え、少し遅れてやってくる、反響音が混じって聞え、より「厚み」のある音になります。

たとえば、相手が自分の耳に直接話しかけてくる、というように直接音が主と予想される場合は、Reflectivityは小さくないと不自然ですが、普通に部屋にいて、そこにおいてあるものの音を聞くなら、反射はある程度必要になるでしょう。

### Reverb (反響）

Reverb propertiesは、大きいホールなどで感じられる反響の強さを設定します。

* Gain (dB)： 反響の強さです。値が低いと、反響は無くなります。
* Brightness：　反響の音の性質です。大きいと高い音の反響が強くなり、小さいと低い音の反響が強くなります。
* Time： 反響の減衰する時間の長さです。値が大きいと、「うわぁんうわぁんうわぁん、、、」という感じ（音楽ホールの中のような雰囲気）で、長く続く反響が聞こえ、小さくなると、すぐに収まる感じ（野外のような雰囲気）の反響になります。

# ２．視線マーカー(ポインター)の使い方

## SDK v0.5xとの違い

v0.5xでは、マーカーとしてスプライトなどのゲームオブジェクトを使いましたが、ver 0.6では以下に示すように、Meshを動的に生成します。そのため、以前のようにスプライトでマーカーを作ることは出来なくなりました。ちょっと残念ですね。その分、マーカーの動きがスムーズになったので、痛し痒しでしょう。


## マーカーのセットアップ

[「THETAとUnityでVR英語教材を作ってみる」](http://qiita.com/yanosen_jp/items/2babf27c2c95f481ae69)という私の以前の記事で紹介したマーカーのセットアップ方法は使えません。新たに「CardboardReticle.prefab」をCardboardMain/Head/MainCamera/の下のヒエラルキーに追加します。

![Reticle.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/7d414cda-b3b3-d165-23b2-6d96d0e38d8a.png)


CardboardReticleオブジェクトには「CardboardRetile」というコンポーネントがあり、以下の二つのパラメータの変更が可能です。

![ReticleParameter.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/c2342001-6c48-ec12-b98e-6d0f02e91b6c.png)


* Reticle Segments: 幾つの線を使ってマーカーの輪郭を描くか。たとえば、３にすると三角形、５にすると五角形になります。

![5kakkei.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/2eaa41dc-8046-b630-6198-c2f52a6162a0.png)


* Reticle Growth Speed：近いものから遠くのものを見たとき、あるいはその反対の際に、マーカーの大きさを変化させるスピード。小さくすると、ゆっくり変化する。

これらのパラメータをもとに、CardboardRetile.csで動的にMeshを生成してマーカーを作っています。

マーカーがオブジェクトに反応するようになるには、EditorのメニューのGameObject/UI/EventSystemでEvent Systemを追加し、それにGazeInputModule.csをアタッチします。

![GazeInputModule.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/51a44ce6-013e-03aa-ad81-f0f30cecec4f.png)


そして、HierarchyでCardboardMain/Head/MainCameraにPhysics Raycasterコンポーネントを加えます。

![PhysicsRaycaster.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/0f335e2f-09d1-0fb3-f6cb-191a7dc6d23b.png)

これで、オブジェクトにマーカーが重なると、マーカーが反応するようになります。

## 視線マーカーに見られるオブジェクトの設定

見られる方のオブジェクトには、Event Triggerコンポーネントを加えます。そして、Add New Event Typeボタンを押して、Pointer Enterを選択すると、マーカーがオブジェクトに重なった時、どのオブジェクトの、どのスクリプトの、どのメソッドを呼ぶのかを選ぶことができます。

![EventTrigger.PNG](https://qiita-image-store.s3.amazonaws.com/0/58503/0d49b0b0-e12b-ad28-9392-6cdb692f098c.png)

これで、視線マーカーでオブジェクトを選択できるようになります。

# おわりに

v0.6は出たばかりで、公式のドキュメントが不完全です。特に、３Dオーディオの部分のパラメータの説明は不正確な可能性もあるので、そこはご容赦いただければ幸いです。