e.blog

主にUnity/UE周りのことについてまとめていきます

Daydream開発はじめたのでメモ

概要

Daydream開発を始めてみたので、色々とメモしていきます。
基本的に気づきベースなので、随時更新していきます。

開発環境の整備

開発環境が整わないと色々と大変なので、Tips的な部分をメモ。

adbをWi-Fi経由で実行する

Daydream開発をしていると、実機インストール→Daydreamデバイスで見る、を繰り返すため、USB接続でやっているととてもめんどくさいです。
しかし、adbにはWi-Fi経由でコマンドを実行する方法が用意されています。

まず、USBで一度Android端末とPCを接続します。
コマンドプロンプトから以下のコマンドを実行することで、以後はWi-Fi経由でコマンドを実行し、ケーブルレスでapkのインストールなども可能になります。

$ adb tcpip 5555
$ adb connect xxx.xxx.xxx.xxx

xxx.xxx.xxx.xxxAndroid端末のIPアドレスです。

接続を解除するには以下のようにします。

$ adb disconnect

コントローラを使う

Daydream Viewには標準でコントローラが付属しています。
そしてDaydreamアプリはコントローラを認識しないと起動しないので、必然的にコントローラが必須となります。

アプリ内でコントローラを利用するにはGvrControllerクラスが提供するプロパティを利用します。
ドキュメントはこちら(Controller API Basics

コントローラの状態を知る

ドキュメントから引用すると、以下の状態を知ることができます。

Buttons

The controller reports the following button properties:

  • ClickButton: True if the Click button (a touchpad click) is currently being pressed.
  • ClickButtonDown: True for 1 frame after user starts pressing the Click button.
  • ClickButtonUp: True for 1 frame after user stops pressing the Click button.
  • AppButton: True if the App button is currently being pressed.
  • AppButtonDown: True for 1 frame after user starts pressing the App button.
  • AppButtonUp: True for 1 frame after user stops pressing the App button.

GvrEventSystemを使う

Google VR SDKから、イベントシステムを利用した、各種イベントの制御の方法が提供されています。
といっても、独自のものはIGvrPointerHoverHandlerのみで、それ以外は通常のuGUIで提供されているインターフェースを実装することでイベントをトラッキングすることができるようになっています。
(例: IPointerClickHandlerなど)

ハマったこと

いくつかハマったことをメモとして残しておきます。

Single Passレンダリングを利用すると色味がおかしくなる

色々な最適化方法を参考に設定を行っていたところ、Single Passレンダリングを有効化して実機確認したところ、色が反転するような現象が現れました。
結論から言うと、Use 32bit Display Bufferをオフにしていると起こるようです。

Daydreamコントローラの感度が悪い

開発をしていて、しばらくしたらどうも「Daydreamコントローラの感度が悪いな・・」と思うことが何度かありました。
いろいろ調べてみると以下の投稿を発見。どうやら、充電がなくなると精度が悪くなるようです。
なので、充電に気をつけて、できるだけフル充電状態で開発ができるようにしておくとよさそうです。

www.reddit.com

Playerにコライダを設定したらイベントが動作しない

GvrEventSystemに則ってイベントを処理していて、とあるタイミングでPlayerにコライダを設定したところ、コントローラのRayが自身にヒットしてしまって一向にオブジェクトに反応しない、ということがありました。

冷静に考えればRayCastなので当たり前ですが、仕組みがそもそもどうやっているのかを把握していなかったので若干ハマりました。
GvrPointerPhysicsRaycasterクラスに、eventMaskというプロパティがあるので、それにマスクを設定しておけば大丈夫です。

例:

GvrPointerPhysicsRaycaster raycaster = GetComponentInChildren<GvrPointerPhysicsRaycaster>();
int playerLayer = (1 << 8);
raycaster.eventMask = ~playerLayer;

ポイントした先にワープするとポインタが正常に動かなくなる

これも理由は上記と同じなのですが、ワープポイントみたいなオブジェクトを作り、それにコントローラで選択させて、決定時にその場所までワープする、みたいなことは比較的やる処理かなと思います。

ただ気をつけないとならないのは、ワープポイントの場所に移動させると、(実装の仕方によっては)コライダの中に入ってしまい、結果そのオブジェクトにコントローラのポインタが取られ続けてしまう、という問題があります。

自分の実装では、プレイヤーがワープポイントにいる間はRaycast向こうなレイヤーに変更し、別の場所に移動したら戻す、ということで対処しました。

AndroidアプリのDaydreamコントローラエミュレータで実機アプリを動かす

Daydreamは、専用コントローラを関連付けないと起動ができません。
(コントローラを認識してね画面から先に進まない)

とはいえ、現状は日本での発売がなく、せっかくDaydream対応端末を買ってもDaydreamコンテンツを楽しむことができません。
そこで、Android上で実行できる、コントローラのエミュレータを使います。

エミュレータはこちらからダウンロードすることができます。
基本的にはPC(開発機)に接続して開発用途として使うものになります。

が、やはり実機での確認は必須。
ということで、これを実機でも利用できるように設定します。

手順としては、

  1. Daydreamアプリを実行するAndroid(実機)と、コントローラ用AndroidBluetoothでペアリングしておく(これはDaydream関係なく普通に設定から行う)
  2. Daydreamアプリ側で、GoogleVR設定画面から「ビルド」を複数回タップして開発者メニューを表示する
  3. 開発者メニューから、コントローラのエミュレータを有効化する
  4. (3)のタイミングで、どのAndroid端末のエミュレータを利用するかリストが表示されるので、(1)で同期した端末を選択する

という流れで行います。

無事に接続が完了すると、エミュレータ画面で「Connected」表示になるので、あとは普通にDaydreamアプリを操作することが可能になります。

フレームレートが出ない

開発をしていて、Physicsを利用してすばやく動かしたオブジェクトがやたらブレて見える現象がありました。 野生の漢さんの記事で書かれている、FixedUpdate周りかなと思って色々やってみたものの変化なし。

そして色々調べていたところ、以下の記事を発見。

https://forum.unity3d.com/threads/best-practice-project-settings-for-daydream.438598/

ここで書かれている以下の項目にしたところだいぶ軽くなりました。

  • Enable 2x Anti Aliasing. (Unity will issue a warning about performance when you build, but it performs fine and looks bad without it.)
  • Disable real time shadows. (They look bad and kill performance.)
  • Disable "Use 32-bit Display Buffer"
  • Stick with Forward or Vertex rendering
  • Enable Multithreaded Rendering
  • Enable Static and Dynamic batching

HDRが有効にならない

Post Processing Stackを使っていて、Bloomが有効にならないなーと思ったら、そもそもHDRが有効になってなかったというオチ。
Graphics Settingsを見てみると、Androidの場合はuse HDRがデフォルトではオフになっているのが原因。それをオンにしたら普通に動きました。

このへんで言及されてるやつ。

github.com

プロファイリング

プロファイリングするにはいくつかのツールがあります。
一番シンプルなのは、ビルトインの内部プロファイラを利用することだと思います。(が、なぜかAndroidでこれが出力できなかった( ;´Д`))
ただ、色々試したのでメモしておきます。

adb logcatでログを出力

AndroidをPCに接続して、以下のようにコマンドプロンプトから実行すると、ログがだーっと出力されます。

$ adb logcat

ただ、これだとAnroid上で実行されているすべてのアプリやシステムのログがすべて出力されてしまうので、Unityだけに絞ります。
具体的には、

$ adb logcat Unity:V *:S

Unity部分がタグで、VVerboseの略、*:Sは、Unityとタグが付いたもの以外のログをすべてSilentにする、という指定です。
これで無事、Unityタグがついたログだけがフィルタリングして出力されるようになります。

ファイル保存

セーブデータなど、ファイルを保存するには保存先パスを指定する必要があります。
保存先パスとしてはApplicationクラスから取得できる以下のパスを利用します。

Application.dataPath

アプリケーションが保存されているパス。

環境 取得パス
Android(本体) /data/app/<アプリのID>.apk
Android(SDカード) /mnt/asec/<アプリのID>/pkg.apk
iOS /var/mobile/Applications/****/myappname.app/Data

Application.persistentDataPath

永続的なデータを保存するパス。 ユーザーデータなど、アプリが再生成できないファイルを配置する。

環境 取得パス
Android(本体) /data/data/<アプリのID>/files/
Android(SDカード) /mnt/sdcard/Android/data/<アプリのID>/files/
iOS /var/mobile/Applications/****/Documents

apkに含まれているManifestの内容を確認する

Daydream向けアプリでは、いくつかの機能の有効化などをManifestに記載する必要があります。
その際、実際にビルドしたapkに該当の項目がしっかり含まれているか、というのを確認したいケースがあります。

それを行うには、aaptというツールがあるので、それを利用します。
aaptは、apktoolsに含まれています)

ibotpeaches.github.io

コマンドは以下のように実行します。

$ aapt l -a hoge.apk

すると、ダーっと色々な情報が出力され、その中にマニフェストの内容も含まれているので、それで内容を確認することが出来ます。

詳細はこちら

stackoverflow.com

参考

logcat コマンドライン ツール  |  Android Developers

docs.unity3d.com

maimai-jp.hatenablog.com

有用リンク