Raspberlyのブログ

Raspberlyのブログ

Unityネタをメインとした技術系ブログです。にゃんこ大戦争や日常なども。そろそろブログタイトル決めたい

【VR開発メモ】視点から遅れて追従するUIを作る【Unity】

 

今回はVR開発ネタをやっていきます。
開発に使うのはOculusQuestですがRift Sなどにもそのまま応用できるかと思います。

 

VRアプリを体験されたり、遊んでいる方はこのようなUIを見たことがあるかと思います。

f:id:Raspberly:20200619004300g:plain
首を振ったり、辺りを見渡すとUIが少し遅れて追従してきますね。

(参考:Robo Recall)

Oculus Integarationに入ってそうですが見つからなかったので、今回はこれを作ってみます。

 

開発環境

Unity 2019.4.0f1

Oculus Integration ver17.0

Oculus Quest

 

セットアップ

まだProjectを作っていない方や初めてVR開発をする方はこちらを参考にしてみてください。
すでに作成済みの方は次へ。

raspberly.hateblo.jp

今回はこのようなSceneを用意しました。
何もないSceneにPlaneとOVRPlayerControllerを設置しています。(Planeは描画だけ切っています)

f:id:Raspberly:20200619004944p:plain

Cameraさえあればなんでもいいです。

 

 

実際にCanvasを作ってみる

VRでは、UIはワールド座標に配置することがほとんどで、
VRゲームのような画面に張り付けるタイプのUIは少なめです。

UnityではCanvasRender Modeを変えることでワールド座標に配置することができます

f:id:Raspberly:20200616223640p:plain


 

ただし、Canvasを作っていきなりモードを変えると設定が少し面倒なので以下の方法がオススメです。

tsubakit1.hateblo.jp

テラシュールブログさんのやり方でCanvasを作ってみます。

Canvasの作成

f:id:Raspberly:20200616224513p:plain

Canvas - Render ModeをScreenSpace-Cameraに変更

CanvasコンポーネントのRender ModeをScreen Space - Cameraに変更します。

f:id:Raspberly:20200616224721p:plain

Render CameraにはSceneに配置されているCameraを設定します。

f:id:Raspberly:20200616225038p:plain

設定するのはOVRCameraRig/TrackingSpace/CenterEyeAnchorです。

f:id:Raspberly:20200616225139p:plain

Plane DIstanceを調整

次にPlane Distanceを設定します。これはCameraとCanvas間の距離です。
プレイヤーに追従するUIとしてなら2~5くらいがちょうどいいかもしれません。

f:id:Raspberly:20200616225633p:plain

これにより、Cameraの前方にCanvasが移動します。大きさもいい感じです。

f:id:Raspberly:20200616230704p:plain

Canvas - Render ModeをWorld Spaceに変更

最後にCanvasのRender ModeをWorld Spaceにして完成です。

f:id:Raspberly:20200616230931p:plain

このやり方ならCanvasのWidth/HeightやScaleを自力で調整する手間がなくなります。

 

ImageやTextの配置

後は適当に画像や文字を配置していけばそれっぽいUIの出来上がりです。

f:id:Raspberly:20200619005430p:plain



 

 

 

必要なコンポーネントの準備

今回やりたいことを実現するためのScriptはこちら。コピペなどでProjectに入れてください。

FollowHUD

Targetを追跡して、位置や角度を追従するコンポーネントです。
このコンポーネントがアタッチされたオブジェクトの子にCanvasを置きます。

パラメータ

Target
 追従するターゲットのTransformです。設定されていない場合Main Cameraを自動的に取得します。

FollowMoveSpeed
 移動速度です。

FollowRotateSpeed
 回転速度です。

RotateSpeedThreshold
 UIとTargetの角度を常に計算し、一定以上離れたら回転速度を上げるようにしています。
このパラメータはそのしきい値です。

isImmediateMove
 有効にすることで位置のみ瞬時に同期するようになります。

isLock
 有効にすることで回転しないようにできます。XYZ個別に設定できます。
 文章を表示するUIはZ軸をLockしておくとよさそう。

 

 

CameraEnable

UI Cameraにアタッチすることで、シーン開始時にCameraを再有効化します。

 

 

 

UIのセットアップ

先ほど作ったCanvasコンポーネントを使って、視点から遅れて追従するUIを作ってみます。

HUDの作成

空のGameObjectを作り、名前を「HUD」(なんでもいい)に変えます。
作ったWorldSpaceのCanvasをHUDの子オブジェクトにします。

f:id:Raspberly:20200618232940p:plain


HUDにFollowCameraコンポーネントをアタッチします。Cameraの設定はしなくても大丈夫です。
他パラメータはお好みで。

f:id:Raspberly:20200618234024p:plain

これで完成です。

f:id:Raspberly:20200619000301g:plain


UIの細かい位置や速度などは実際に動かしながら調整するといいでしょう。

CanvasのPositionなどを調整

HUDのPositionはCameraと同じ値にしておくと調整が楽になります。
Cameraからの距離はCanvasを、細かい位置や角度はUI部品個別に調整するといいかも。

f:id:Raspberly:20200618234627p:plain

 

ちなみに、HUDを複数用意してSpeedを変えておくとバラバラに追従します

f:id:Raspberly:20200619003702g:plain



 

 

 

UIがオブジェクトに隠れてしまう時の対処法

WorldSpaceのUIの問題点として他のオブジェクトに隠れてしまう点があります。
床や壁、多数のオブジェクトがある場合困りますね。

f:id:Raspberly:20200619001251g:plain



対処方としては、UI用のCameraを新たに作成するのが手っ取り早いです。

Cameraの作成

CenterEyeAnchorDuplicate(オブジェクトの複製)し、名前をUI Cameraに変更します。
Audio Listenerは消しておきましょう。

f:id:Raspberly:20200618015843g:plain

UIのみ映るようにする

CameraコンポーネントCulling MaskをUIのみに設定します。
CameraはCulling Maskに設定したレイヤーのオブジェクトのみ描画します。

f:id:Raspberly:20200617233249g:plain

Clear FlagsをDepth onlyに

Clear FlagsをDepth onlyにします。

f:id:Raspberly:20200617233626p:plain

元のCameraにUIは映らないようにする

CenterEyeAnchorのCulling MaskからUIを外しておきます。
これでUIだけ映らなくなります

f:id:Raspberly:20200619000953p:plain


これで完成・・・ではないんです。実はもう一段落あります

 

アクティブな2つ目以降のCameraが正常に動かなくなる問題の解決

Scene内にアクティブなCameraが複数ある場合、1つを除いて正常に動かなくなる場合があります。
Oculus Integrationの何かがやっているとは思いますが、原因はわからず。。。


一度Cameraのenableを切り替えたり、オブジェクト自体の再アクティブ化を行えば治ります。 
先ほど紹介したCameraEnableコンポーネントをそのままアタッチすれば問題ありません。

f:id:Raspberly:20200619000541p:plain

これで完成です。
地形や障害物に影響されず最前列にUIが表示されるようになりました。

f:id:Raspberly:20200619001654g:plain

 

 

まとめ

・FollowHUDコンポーネントを使うことで、視点から遅れて追従するUIを作る

・UIが他のオブジェクトに隠れてしまう場合は、UI用のCameraを作ることで最前列に表示できる

 

 

 

その他

この記事を書いている最中に良さそうなアセットを見つけました。

紹介記事はこちら

raspberly.hateblo.jp

 

 

余談

HoloLensの話ですが、実はこのようなオブジェクトの配置方法はBody-Lockedと呼ばれているそうです。

HoloLens でのオブジェクトの配置は大きく 3 種類にわけられ、Body-Locked はその内の一つという位置づけです。

  • World-Locked
    • 現実の位置に重ねて表示
  • Display-Locked
    • ディスプレイ上に固定
  • Body-Locked
    • 視界の範囲内で遅延させて表示

tips.hecomi.com

 

 

参考文献

bibinbaleo.hatenablog.com

bibinbaleo.hatenablog.com

 

qiita.com

naichilab.blogspot.com

VRゲームプレイ「Robo Recall(ロボリコール)」vol.1 with Oculus

 

 

 

他のVR開発メモはこちら 

raspberly.hateblo.jp

 

 

他間違っている箇所がありましたらコメントにお願いします。