ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »VR
このページの記事一覧

【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする  


 これは音量操作のプラグインのアップデート版となる。以前の記事にはプラグインの内部的なコード(Java)や仕様説明を書いたので、今回は Unity 側のコードやプレファブの使い方などを中心に書いておこう。プラグイン自体のセットアップからはじめる場合は、以前の記事を参照して欲しい。

>>プラグイン&サンプルをダウンロード
(Google Drive を利用。画面右上にあるダウンロードアイコンを押す)



(※) Unity 5.6.3p1 / AndroidStudio 2.3.3 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認



■ハードウェア音量操作する際の AndroidManifest.xml について

 プラグインのセットアップにも書いてあるが、ここではもう少し詳細に解説しておこう。ハードウェア音量ボタンを押したときのイベントを取得する際には Unity で通常使われるアクティビティ「UnityPlayerActivity」をオーバーライドした、「HardVolKeyOnUnityPlayerActivity」(ハードウェア音量イベント取得用アクティビティ:プラグイン内に入っている)または「FullPluginOnUnityPlayerActivity」(プラグイン機能のすべてが入っている)を使う必要がある。これらのアクティビティ(Activity)はこのプラグイン独自のアクティビティで、ハードウェアキーのイベントを監視するコードが含まれている(初期のバージョンではあるが、Java コードは以前の記事に掲載してある)。インポートした「Assets/Plugins/Android/」にはマニフェストファイルのテンプレとして「AndroidManifest-HardVolKey~.xml」または「AndroidManifest-FullPlugin~.xml」が含まれているので、これらの中から適切なものを選んで(「縦置き・横置き」とか「API Level」とか)、「AndroidManifest.xml」にリネームしてビルドすることで利用することが可能になる。音量の取得・増減だけなら特別な権限はいらないので、使用するアクティビティさえ指定すれば、独自に書き換えても構わない。


 なお、ハードウェアボタンのイベントを受け取らず、Unity から一方的に音量を設定するだけなら、オーバーライドしたアクティビティを使う必要はない。具体的には例えば、後述する「GetMediaVolume()」「SetMediaVolume()」「AddMediaVolume()」(ハードウェア音量[メディア音量のみ]の取得と設定)のみの使用なら、これらマニフェストファイルは必要ない(Unity がデフォルトのマニフェストファイルを用意してくれる)。

(※) 独自のマニフェストファイルでビルドすると警告「Unable to find unity activity in manifest. You need to make sure orientation attribute is set to sensorPortrait manually.」が出るが、「UnityPlayerActivity」以外のアクティビティを使うと出るものなので気にしなくて良い(orientation=画面回転はUnity側のアプリの設定に合わせた方が良い)。



■HardVolumeController(プレファブ)の使い方

 サンプルシーンにも含まれている「HardVolumeController.prefab」はスクリプト「HardVolumeController.cs」をアタッチしたハードウェア音量操作をするプレファブである。同じように「HardVolumeControllerWithToast.prefab」「HardVolumeControllerWithToast.cs」というものも入っているが、これらは音量が操作されたときにプラグインでトースト(Toast)で現在音量を表示する機能を追加しただけのものである。つまり音量の表示方法以外は内容的に変わらないので、例ではどちらの場合でも置き換えて考えて欲しい。

 端末と連携してこれらプレファブを利用するには、オプションの設定とコールバックを上手く使う必要がある。少しその辺は紛らわしいので、その解説と設定例などをなるべく詳細に書いておこう。


●オプション設定やコールバックの説明
Enable Hard Keyこのスクリプトからは常にハードウェアの音量操作はできるのだが(Unity → Android)、端末のハードボタンを押したときにもスクリプトを利用するか否かの設定(Android → Unity[→何らかの動作])をするオプションとなる。別の言い方をすれば、「端末のハードボタンを押したときのイベントを受け取るか否か」と同義だ。端末のハードボタンと連携したいときはオンにする必要がある。オンにしたとき、端末のハードボタンで音量大を押すと Android → Unity へ "VolumeUp" メッセージ(文字列)が送られ、コールバック:OnHardVolumeKeyUp() が呼ばれる。同じようにハードボタンで音量小を押したときは Android → Unity へ "VolumeDown" メッセージが送られ、コールバック:OnHardVolumeKeyDown() が呼ばれる。インスペクタでこれらコールバックに何らかのメソッドを登録しておけば、端末のハードボタンを操作したとき独自のアクションが設定できる。オフにしたときは、端末のハードボタンのイベントを無視するので、端末側で操作したときの影響は受けない(端末での操作とは別々になる)。デフォルトはオフ(Unityでの操作、端末での操作は別々に行える)。
Hard Operation端末のハードボタンを押したとき、端末自身での音量操作をするか否かのオプション。オフにすると端末自身での音量操作は無効となり、Unity 側だけの音量操作となる。「Enable Hard Key」をオンにすることでハードボタン押下のイベントは受け取れるので、「Hard Operation=オフ+Enable Hard Key=オン」の組み合わせで「Android 端末で音量無効→イベントだけUnityで受け取る→コールバックでUIなどを表示→UnityからAndroidへ音量設定」のような流れを作ることで Unity 側でのハード音量操作を完全に制御できる。逆に「Hard Operation=オフ+Enable Hard Key=オフ」にするとユーザーは音量操作が全くできなくなってしまうので注意。デフォルトはオン(Android端末側でも音量操作は可能)。
Show UIUnity で音量操作を行ったとき、端末のシステムUIを表示するか否かのオプション。あくまで Unity 側からの操作のときのみなので、端末自身のハードボタンで操作したときには影響しない。
On Volume Called(int)
(コールバック)
音量の増減操作や現在の音量取得をしたときのコールバック。通常は UI などの呼び出しに使うと良い。「HardVolumeControllerWithToast」はこのコールバックでトースト(Toast)を呼び出すセットアップがされている。独自の UI などを作成したときはここにその表示メソッドを登録すれば良いだろう。引数の値(整数)は操作後の音量となる。
On Hard Key Volume Up
(コールバック)
端末のハードボタンで音量が上げられたときのコールバック。ハードボタン押下のイベントを受け取る必要があるので「Enable Hard Key=オン」である必要がある。「Hard Operation=オフ」のときは、端末自身で音量操作ができなくなるため、ここに音量アップのメソッドを登録すると良い(HardVolumeController.VolumeUp() でも良い)。「Hard Operation=オン」のときは、端末自身で音量操作ができるため、現在音量の表示だけで良いだろう(HardVolumeController.VolumeNow() 等)。逆にハードボタンを無視するならば登録する必要はない。
On Hard Key Volume Down
(コールバック)
端末のハードボタンで音量が下げられたときのコールバック。ハードボタン押下のイベントを受け取る必要があるので「Enable Hard Key=オン」である必要がある。「Hard Operation=オフ」のときは、端末自身で音量操作ができなくなるため、ここに音量アップのメソッドを登録すると良い(HardVolumeController.VolumeDown() でも良い)。「Hard Operation=オン」のときは、端末自身で音量操作ができるため、現在音量の表示だけで良いだろう(HardVolumeController.VolumeNow() 等)。逆にハードボタンを無視するならば登録する必要はない。




■HardVolumeController のセットアップ例

 言葉で説明すると少し難しく感じるので、簡単なセットアップ例を掲載しておこう。サンプルのシーンには微妙に異なったセットアップのプレファブが配置してあるので、動作確認して自分の使いたい機能に近いものを利用するのも良いだろう。

(例1)端末自身のハードボタン・Unity ともに音量操作をしたとき、端末のシステムUIとトースト(Toast)が表示されるセットアップ。
(※)サンプルのシーン「Assets/_Test/Scenes/PluginTest」に配置してある。


Enable Hard Key → ハードボタンのイベントを受け取る。
Hard Operation → 端末自身での音量操作も可能とする。
Show UI → Unity で音量操作をしたときも端末のシステムUIを表示する。
On Volume Called → Unity, 端末自身ともに音量操作したとき、トーストを表示する。
On Hard Key Volume Up →ハードボタンで音量を上げるイベントを受信したとき、現在音量を表示する(→トーストで表示される)。
On Hard Key Volume Down → ハードボタンで音量を下げるイベントを受信したとき、現在音量を表示する(→トーストで表示される)。



(例2)端末のハードボタンが押されたとき、Unity で独自の UI にて現在音量を表示し音量操作をする。また端末のシステムUIは表示しないセットアップ。
(※)サンプルのシーン「Assets/_Test/Scenes/DialogExTest」に配置してある。


(※)「VolumeUI」は独自のUI(uGUI)

Enable Hard Key → ハードボタンのイベントを受け取る。
Hard Operation → 端末自身での音量操作を無効化する(システムUIを表示させない)。
Show UI → Unity で音量操作をしたときに端末のシステムUIを表示しない。
On Volume Called → Unity, 端末自身ともに音量操作したとき、独自UIを表示する。
On Hard Key Volume Up → ハードボタンで音量を上げるイベントを受信したとき、Unity で端末の音量を上げる。
On Hard Key Volume Down → ハードボタンで音量を下げるイベントを受信したとき、Unity で端末の音量を下げる。




■スクリプトでハードウェア音量操作・取得などをする [メディア音量のみ]

 以前の記事にもコードは掲載してあるが、ここでは改めて機能ごとに分けて書いておこう。

●ハードウェア音量を取得する [メディア音量のみ]
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
int vol = AndroidPlugin.GetMediaVolume(); //現在音量の取得
int max = AndroidPlugin.GetMediaMaxVolume(); //最大音量の取得
#endif

//HardVolumeController を使用するなら(内容は全く同じ)
HardVolumeController hardVolumeController = FindObjectOfType<HardVolumeController>();
int vol = hardVolumeController.volume; //現在音量の取得
int max = hardVolumeController.maxVolume; //最大音量の取得


●ハードウェア音量を設定・増減をする [メディア音量のみ]
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
int vol = AndroidPlugin.SetMediaVolume(4, showUI); //音量=4
vol = AndroidPlugin.SetMediaVolume(0, showUI); //ミュート:音量=0
vol = AndroidPlugin.AddMediaVolume(1, showUI); //現在の音量+1
vol = AndroidPlugin.AddMediaVolume(-1, showUI); //現在の音量-1
#endif

//HardVolumeController を使用するなら(内容は全く同じ)
HardVolumeController hardVolumeController = FindObjectOfType<HardVolumeController>();
hardVolumeController.volume = 4; //音量=4
hardVolumeController.VolumeMute(); //ミュート:音量=0
hardVolumeController.VolumeUp(); //現在の音量+1
hardVolumeController.VolumeDown(); //現在の音量-1


●ハードウェアボタン押下による、端末自身での音量操作を有効/無効化する
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.HardKey.SetVolumeOperation(true); //端末自身での音量操作が可能
AndroidPlugin.HardKey.SetVolumeOperation(false); //端末自身での音量操作を無効化
#endif

//HardVolumeController を使用するなら(内容は全く同じ)
HardVolumeController hardVolumeController = FindObjectOfType<HardVolumeController>();
hardVolumeController.HardOperation = true; //端末自身での音量操作が可能
hardVolumeController.HardOperation = false; //端末自身での音量操作を無効化


●ハードウェアボタン押下のイベントを取得するリスナーを登録する
using FantomLib;

void OnEnable() //MonoBehaviour イベント
{
#if UNITY_ANDROID && !UNITY_EDITOR
//ハードウェア音量キーのリスナー登録("HardVolumeKeyChange"はコールバックハンドラ)
AndroidPlugin.HardKey.SetKeyVolumeUpListener(gameObject.name, "HardVolumeKeyChange", "VolumeUp");
AndroidPlugin.HardKey.SetKeyVolumeDownListener(gameObject.name, "HardVolumeKeyChange", "VolumeDown");
#endif
}

void OnDisable() //MonoBehaviour イベント
{
#if UNITY_ANDROID && !UNITY_EDITOR
//ハードウェア音量キーの全リスナー解除
AndroidPlugin.HardKey.RemoveAllListeners();
#endif
}

//ハードウェア音量キーのイベントハンドラ(Android ネイティブから呼ばれる)
void HardVolumeKeyChange(string message)
{
if (message == "VolumeUp")
{
//音量を上げる操作されたときの処理
}
else if (message == "VolumeDown")
{
//音量を下げる操作されたときの処理
}
}

//※内容は「HardVolumeController.cs」と同じもの。

 サンプルコードは「Assets/FantomLib/Scripts/Module/HardVolumeController.cs」にまとまっているので適当にコピペしたり、継承して新しいクラスを作るのも良いだろう。またプレファブ「Assets/FantomLib/Prefabs/System/HardVolumeControllerWithToast」にはトースト(Toast)で操作したときの音量を表示できるようにセットアップしてある。少し改造すればVR(Cardboard/ハコスコ)にも応用できるだろう。シーン「PluginTest」「DialogTest」「DialogExTest」にはそれぞれ異なったセットアップのプレファブが配置がされているので、自分の好みに合ったものを利用するのも良いだろう。

(※) Unity 2017.2.0f3 でビルド / Galaxy S7 Edge (Android 7.0) で確認

(その他動作確認した機器)



(関連記事)
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】Androidでカスタマイズしたダイアログを動的生成できるプラグインを作ってみた
【Unity】Androidでスライダーで設定を変更するダイアログを使う
【Unity】Androidでスイッチで設定を変更するダイアログを使う
【Unity】Androidの選択ダイアログを使う
【Unity】Androidで日付・時刻選択ダイアログ(DatePicker, TimePicker)を使う
【Unity】Androidで数値・半角英数・パスワード入力ダイアログを使う
【Unity】Androidでテキスト入力ダイアログを使う
【Unity】Androidのテキスト読み上げ(TextToSpeech)を使う
【Android】【Java】AlertDialog を使ってみる


スポンサーサイト

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  Unityプラグイン  Cardboard  VR 
tb: 0   cm: --

【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた  


 元々は GearVR のように、Cardboard/ハコスコVR でも BlueToothコントローラ を使って手元で音量操作できたら便利だろうな~って思って色々試してたんだけど、そのついでにAndroidに標準で備わっているトースト(Toast)やダイアログ(AlertDialog)、通知(Notification)、音声認識(SpeechRecognizer)なども使える簡単なプラグインを作ってみた。単純な機能しかないが、ブラウザなどでURL先を開く機能なども付けておいたので、アプリ内に書ききれない説明ページやサポートページなどのHPを開くボタンなどを作るのも良いだろう。簡単なものだがパッケージにはサンプルも付けておいたので、コピペするなり改造するなりして自由に使って欲しい。

※AssetStore版 FantomPluginのセットアップはこちら

>>プラグイン&サンプルをダウンロード
(Google Drive を利用。画面右上にあるダウンロードアイコンを押す)

※基本的にアセットストアのものとコードは同じになりますが、
アセットストア版は審査のためリリースが少し遅れるのと、規定上英語でのコメントが中心になります。



■プラグインのセットアップ(GoogleDrive 版)
■プラグインのセットアップ(AssetStore 版)
■トーストを使う(Toast)
■Yes/No ダイアログを使う(AlertDialog)
■OK ダイアログを使う(AlertDialog)
■チェックボックス付き Yes/No ダイアログを使う
■チェックボックス付き OK ダイアログを使う
■単一選択ダイアログ①を使う(AlertDialog) [確認ボタン無し]
■単一選択ダイアログ②を使う(AlertDialog) [確認ボタン有り]
■複数選択ダイアログを使う(AlertDialog)
■単一行テキスト入力ダイアログを使う(AlertDialog)
■複数行テキスト入力ダイアログを使う(AlertDialog)
■数値入力のテキストダイアログを使う(AlertDialog)
■半角英数入力のテキストダイアログを使う(AlertDialog)
■パスワード入力のテキストダイアログを使う(AlertDialog)
■日付選択ダイアログを使う(DataPickerDialog)
■時刻選択ダイアログを使う(TimePickerDialog)
■スイッチダイアログを使う
■スライダーダイアログを使う
■カスタムダイアログを使う
■通知を使う(Notification) [タッチでアプリに戻る]
■通知を使う(Notification) [タッチでURLを開く]
■URLを開く [任意のアクション]
■音声認識のダイアログを使う(SpeechRecognizer)
■音声認識をダイアログなしで使う(SpeechRecognizer)
■テキスト読み上げ機能を使う(TextToSpeech)
■ハードウェア音量の取得・設定など [メディア音量のみ]
■ハードウェア音量操作のイベントを取得する [メディア音量のみ]
■ハードウェア音量キーの無効化をする
■ピンチ操作の取得
■スワイプ(フリック)操作の取得
■長押し(ロングタップ)操作の取得
■ゼンサーを使う(歩数計・心拍数など)
■Android ビルドをもう少し詳しく
 ●パーミッションの設定
 ●センサー利用時のフィルタリング(Google Play)
 ●画面回転の設定
■更新履歴
■ユニティちゃんと音声認識でじゃんけん(Android 版デモ)
■ユニティちゃんがアキバ上空を飛ぶ!(SmoothFollow3 デモ)

(※) Unity 5.6.3p1 / AndroidStudio 2.3.3 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認



■プラグインのセットアップ

 まずはアーカイブを解凍したら、「FantomPluginAndroid.unitypackage」をプロジェクトにインポートしよう。もちろん機能を使うには「Build Settings..」を「Andrdoid」にする必要があるが、どのみちエディタ上では動作確認はできないので、最終的にはビルドして実機で確認する必要がある。


 プラグインの実体は「Assets/Plugins/Android/」にある「fantomPlugin.aar」になる。プラグインは「Minimum API Level:Android 4.2 (API 17) 」で作られているので、ビルドする際には API17 以上に設定して欲しい。


 また、同じフォルダに複数の「AndroidManifest-~.xml」があるが、これは使いたい機能や画面の回転方向("_Landscape"または"_Portrait")、テーマ("_API17"または"_API21")などの設定テンプレで、ビルドする際に適切なものを選んで「AndroidManifest.xml」にリネームして使って欲しい。例えば、「ハードウェア音量のイベント取得」には "-HardVolKey" が付いたものを、「音声認識のダイアログ」を使うには "-Speech" が付いたものを使う必要がある。これら機能を利用するには元のアクティビティ「UnityPlayerActivity」をオーバーライドした、「HardVolKeyOnUnityPlayerActivity」(ハードウェア音量イベント取得用アクティビティ:プラグイン内に入っている)、「ReceiveResultsOnUnityPlayerActivity」(音声認識ダイアログ結果取得用アクティビティ:プラグイン内に入っている)を使う必要があるので、それらを指定したマニフェストファイルとなっている。また、両方使いたい場合は "-FullPlugin" の付いたもの(プラグイン内に入っている)を使えば良い(「FullPluginOnUnityPlayerActivity」にはプラグイン機能のすべてが入っている)。これらマニフェストファイルは手動で書き換えても構わない(※ただし音声認識を使う場合は、録音パーミッション「RECORD_AUDIO」も必要)。

(参考)UnityPlayerActivity Java コードの拡張

 なお、"_API17"または"_API21"の名前は使えるテーマの API Level で分類されているが、これは主に「Theme.DeviceDefault.Light.NoActionBar.Fullscreen」(API17から)、「Theme.Material.Light.NoActionBar.Fullscreen」(API21から)というだけで内容は同じだ。元の「UnityPlayerActivity」をオーバーライドして起動すると、Unityが完全に起動するまでにアクションバーなどが表示されることがあるので、それを回避するために使っているものだ。これらはダイアログにも適用されるので注意しよう(※ダイアログごとに設定することはできる)。任意に変更しても構わない。ちなみに".Light"が付いているテーマは白系ベースで、付いてないものは黒系ベースとなる。テーマの名前のアンダバー("_")をドット(".")に変更したものを指定する。

(参考)R.Style.Theme

 あと、サンプルデモをビルドするには「AndroidManifest_test.xml」をリネームして「AndroidManifest.xml」にすれば全機能使える(※"-FullPlugin" と内容的には同じ)。「BuildSettings...」に「Assets/_Test/Scenes/」にあるシーンを追加してビルドするのも忘れずに。


(※) ビルドすると警告「Unable to find unity activity in manifest. You need to make sure orientation attribute is set to sensorPortrait manually.」が出るが、独自の「AndroidManifest.xml」(UnityPlayerActivity以外のもの)を使うと出るものなので気にしなくて良い(orientation=画面回転はUnity側のアプリの設定に合わせた方が良い)。


 以下には各機能の使用する際の簡単なC#コードと解説、プラグインとして作った元のJavaコードの一部(簡略化したもの)を書いておこう。簡易説明書のように使って欲しい。JavaでAndroidのアプリを作ったことがあるなら、対応するパラメタを見た方が理解しやすく応用範囲も広いものになるだろう。



■トーストを使う(Toast)


●Unity から Android の Toast を使う C# コード
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowToast(message);
#endif

●プラグイン内の対応する Java コード
import android.content.Context;
import android.widget.Toast;

Toast.makeText(context, message, duration).show();

 トースト(Toast)は画面の下の方に出る、短い時間表示されるメッセージである。

 C# 側の引数はメッセージ文字列(message)と表示長さのフラグ(longDuration)となっている。長さはJava 側で「LENGTH_SHORT」「LENGTH_LONG」しかないので、フラグで置き換えている。context は起動アクティビティのことを指していて、AndroidPlugin のメソッド内で自動取得されるので必要ない。

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「ShowToast()」「TestToast()」あたりを見て欲しい。



■ダイアログを使う(AlertDialog) [Yes/No 2択]


●Unity から Android の AlertDialog を使う C# コード(Yes/No ダイアログ)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowDialog(title, message, callbackGameObject, callbackMethod, yesCaption, yesValue, noCaption, noValue, style);
#endif

●プラグイン内の対応する Java コード
import android.app.AlertDialog;
import android.content.DialogInterface;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
switch(which) {
case DialogInterface.BUTTON_POSITIVE:
UnitySendMessage(callbackGameObject, callbackMethod, yesValue);
break;
case DialogInterface.BUTTON_NEGATIVE:
UnitySendMessage(callbackGameObject, callbackMethod, noValue);
break;
}
}
};

AlertDialog.Builder builder = new AlertDialog.Builder(context, styleId);

builder.setTitle(title)
.setMessage(message)
.setPositiveButton(yesCaption, listener)
.setNegativeButton(noCaption, listener)
.show();

 これは「はい/いいえ」の2択のダイアログ(AlertDialog)である。戻値は「はい」のとき「yesValue」、「いいえ」のとき「noValue」がヒエラルキーにある GameObject 名(callbackGameObject)のメソッド(callbackMethod)に文字列で返ってくる。また Andrdoid のダイアログの場合、範囲外をクリックするとダイアログが消えるが、その場合は何も返って来ない。つまり実質3択のようになる(「はい/いいえ/あとで」→「Yes/No/(なし)」みたいな)。コールバックするメソッドのシグネチャは文字列型(string)固定になる(というより基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に変換して使う)。

 ダイアログにはスタイル(テーマ)を当てられるようにしてある。省略=空文字("")のときはアクティビティのテーマと同じものになる。スタイルの引数は "android:Theme.DeviceDefault.Dialog.Alert" のように、名前のアンダバー("_")をドット(".")に変えたものを指定する。端末の API Level によって使えるものとそうでないものがあるので、アプリのビルドの API Level に合わせて指定する必要があるので注意。

(参考)R.style.theme

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestDialogYesNo()」あたりを見て欲しい。



■ダイアログを使う(AlertDialog) [OK のみ]


●Unity から Android の AlertDialog を使う C# コード(OK ダイアログ)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowDialog(title, message, callbackGameObject, callbackMethod, okCaption, resultValue, style);
#endif

●プラグイン内の対応する Java コード
import android.app.AlertDialog;
import android.content.DialogInterface;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

DialogInterface.OnDismissListener listener = new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
UnitySendMessage(callbackGameObject, callbackMethod, resultValue);
}
};

AlertDialog.Builder builder = new AlertDialog.Builder(context, styleId);

builder.setTitle(title)
.setMessage(message)
.setPositiveButton(okCcaption, null)
.setOnDismissListener(listener)
.show();

 これは注意喚起を促すだけの「OK」のみのダイアログ(AlertDialog)である。戻値は必ず「resultValue」がヒエラルキーにある GameObject 名(callbackGameObject)のメソッド(callbackMethod)に文字列で返ってくる。また Andrdoid のダイアログの場合、範囲外をクリックするとダイアログが消えるが、その場合も「resultValue」が返ってくる。つまりダイアログが閉じられたタイミングを受け取るだけの値となる。コールバックするメソッドのシグネチャは文字列型(string)固定になる(というより基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に変換して使う)。

 ダイアログにはスタイル(テーマ)を当てられるようにしてある。省略=空文字("")のときはアクティビティのテーマと同じものになる。スタイルの引数は "android:Theme.DeviceDefault.Dialog.Alert" のように、名前のアンダバー("_")をドット(".")に変えたものを指定する。端末の API Level によって使えるものとそうでないものがあるので、アプリのビルドの API Level に合わせて指定する必要があるので注意。

(参考)R.style.theme

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestDialogOK()」あたりを見て欲しい。



■通知を使う(Notification) [タッチでアプリに戻る(起動してないときは起動する)]


●Unity から Android の Notification を使う C# コード(タッチでアプリに戻る(起動してないときは起動する))
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowNotification(title, message, iconName, tag, showTimestamp);
#endif

●プラグイン内の対応する Java コード
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;

Intent intent = new Intent(context, context.getClass());
PendingIntent pendingIntent = PendingIntent.getActivities(context, 0, new Intent[]{intent}, 0);

Notification notif = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(iconId)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build();

NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(tag, 0, notif);

 これは注意喚起を促すだけの通知(Notification)である。タッチでアプリに戻るようにしてある(起動してないときは起動する)。

 Unity の場合、自分でマニフェストファイルを書き換えない限りはアイコン名(iconName)は "app_icon" が使われる。タグは複数回通知したとき、同じタグを持つものは上書きされる(つまり最新のものだけ表示する)というものである。通知時刻は showTimestamp をオフにすれば消すことができる。デフォルトはオンになる。

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestNotification()」あたりを見て欲しい。



■通知を使う(Notification) [タッチでURLを開く]


●Unity から Android の Notification を使う C# コード(タッチでURLを開く)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowNotificationToOpenURL(title, message, url, tag, showTimestamp);
#endif

●プラグイン内の対応する Java コード
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;

Intent intent = new Intent(action, Uri.parse(url));
PendingIntent pendingIntent = PendingIntent.getActivities(context, 0, new Intent[]{intent}, 0);

Notification notif = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(iconId)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build();

NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(tag, 0, notif);

 これはタッチをすると指定したURLを開く(起動アプリは端末による)通知(Notification)である。AndroidPlugin.ShowNotificationToActionURI() でアクションをURLを開くこと専用にしたものでもある。Java コードの引数の「action」が「android.intent.action.VIEW」のときURLを渡すとブラウザ等で開くことになる(※端末のデフォルトアプリの設定による)。タッチによる動作以外は「通知でアプリに戻る」と変わらない。

 AndroidPlugin.ShowNotificationToActionURI() でアクションと URI を組み合わせて使う分には他の使い方もできるかも知れない。アクションについては以下を参照して欲しい(Constant Value を使う)。

(参考)Intent.ACTION~

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestNotification()」あたりを見て欲しい。



■URLを開く [任意のアクション]


●Unity から Android 端末でURLを開く
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.StartOpenURL(url);
#endif

●プラグイン内の対応する Java コード
import android.app.Activity;
import android.content.Context;
import android.content.Intent;

Intent intent = new Intent(action, Uri.parse(url));
startActivity(intent);

 これは直接 URL を開くアクションをするメソッドである。「通知からURLを開く」と動作は変わらないが、Unity のボタンでも画像でも好きなUIなどに付けて使うものとして作ってみた。AndroidPlugin.StartActionURI() でURLを開くこと専用にしたものでもある(引数の「action」が「android.intent.action.VIEW」になっている)。

 AndroidPlugin.StartActionURI() でアクションと URI を組み合わせて使う分には他の使い方もできるかも知れない。アクションについては以下を参照して欲しい(Constant Value を使う)。

(参考)Intent.ACTION~

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestOpenURL()」あたりを見て欲しい。



■音声認識のダイアログを使う(SpeechRecognizer)


●Unity から Android の SpeechRecognizer を使う C# コード(ダイアログを表示して取得)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowSpeechRecognizer(callbackGameObject, resultCallbackMethod, message);
#endif

●プラグイン内の対応する Java コード
//音声入力ダイアログ表示
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.content.Intent;

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, message);
startActivityForResult(intent, 0);


//認識された文字列の受信とコールバック
import android.speech.RecognizerIntent;
import android.content.Intent;
import java.util.List;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

public class ReceiveResultsOnUnityPlayerActivity extends UnityPlayerActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (data.hasExtra(RecognizerIntent.EXTRA_RESULTS)) {
List results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);

string str = "";
for (String s : results) {
if (str.length() > 0)
str += "\n";
str += s;
}

UnitySendMessage(callbackGameObject, resultCallbackMethod, str);
}
}
}
}

 これは音声入力のダイアログを表示して、認識できた文字列を受信→Unity へコールバックするやり方である。認識できた文字列またはエラーはヒエラルキーにある GameObject 名(callbackGameObject)のメソッド(resultCallbackMethod)に文字列で返ってくる。認識された文字列は改行("\n")区切りで結合されて、Unity 側へコールバックメソッドの引数で返される。1つずつ取り出すには String.Split() などを使って分割すれば良い(基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に処理して使う)。

 この結果受信の実装は「ReceiveResultsOnUnityPlayerActivity」に書かれていて、元の「UnityPlayerActivity」(デフォルトでAndroidビルドに使用されているアクティビティ)をオーバーライドして使う必要がある(マニフェストファイルの「-Speech」が付いているものに設定されている)

 結果受信の実装方法などは別ページにまとめておいたので、必要あればそちらも参照。
ダイアログを使用した音声認識の利用方法

 サンプルコードは「Assets/_Test/Scripts/SpeechRecognizerTest.cs」の「ShowSpeechRecognizer()」「ResultSpeechRecognizer()」あたりを見て欲しい。

(音声認識 参考)




■音声認識をダイアログなしで使う(SpeechRecognizer)


●Unity から Android の SpeechRecognizer ダイアログなしで使う C# コード(イベントを取得して自前で処理する)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.StartSpeechRecognizer(callbackGameObject, resultCallbackMethod, errorCallbackMethod,
readyCallbackMethod, beginCallbackMethod);
#endif

●プラグイン内の対応する Java コード
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.content.Intent;

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, context.getPackageName());

SpeechRecognizer recognizer = SpeechRecognizer.createSpeechRecognizer(context);
recognizer.setRecognitionListener(new RecognitionListener() {
@Override
public void onReadyForSpeech(Bundle params) {
UnitySendMessage(callbackGameObject, readyCallbackMethod, "onReadyForSpeech");
}

@Override
public void onBeginningOfSpeech() {
UnitySendMessage(callbackGameObject, beginCallbackMethod, "onBeginningOfSpeech");
}

@Override
public void onError(int error) {
UnitySendMessage(callbackGameObject, errorCallbackMethod, String.valueOf(error));
}

@Override
public void onResults(Bundle results) {
List list = results.getStringArrayList(android.speech.SpeechRecognizer.RESULTS_RECOGNITION);

string str = "";
for (String s : list) {
if (str.length() > 0)
str += "\n";
str += s;
}

UnitySendMessage(callbackGameObject, resultCallbackMethod, str);
}

//・・・(略)・・・
});

recognizer.startListening(intent);

 これは音声入力のダイアログは表示しないで、待機イベント(onReadyForSpeech()→readyCallbackMethod)、入力開始イベント(onBeginningOfSpeech()→beginCallbackMethod)、認識結果イベント(onResults()→resultCallbackMethod)またはエラー(onError()→errorCallbackMethod)のイベントをこの順にコールバックするやり方である。それぞれのイベントで Unity 側でアニメーションしたり、状態表示をすれば良い。なお、待機イベント(onReadyForSpeech)は必ず文字列 "onReadyForSpeech" を、認識開始イベント(onBeginningOfSpeech) は "onBeginningOfSpeech" を返す。これはタイミングを知るためだけのイベントであり、省略しても構わない(結果とエラーだけでも使うことはできる)。

 認識された文字列は改行("\n")区切りで結合されて、Unity 側へコールバックメソッドの引数で返される。この場合はヒエラルキーにある GameObject 名(callbackGameObject)の結果受信メソッド(resultCallbackMethod)またはエラー受信メソッド(errorCallbackMethod)に引数の文字列で返ってくる。1つずつ取り出すには String.Split() などを使って分割すれば良い(基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に処理して使う)。

 コールバックの実装方法などは別ページにまとめておいたので、必要あればそちらも参照。
コールバックを実装した音声認識の利用方法

 サンプルコードは「Assets/_Test/Scripts/SpeechRecognizerTest.cs」の「StartSpeechRecognizer()」「OnReady()」「OnBegin()」「OnResult()」「OnError()」あたりを見て欲しい。

(音声認識 参考)




■ハードウェア音量の取得・設定など [メディア音量のみ]


●Unity から Android のハードウェア音量を取得・設定する(メディア音量のみ)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
int max = AndroidPlugin.GetMediaMaxVolume(); //最大音量の取得
int vol = AndroidPlugin.GetMediaVolume(); //現在音量の取得
vol = AndroidPlugin.AddMediaVolume(1, showUI); //現在の音量+1
vol = AndroidPlugin.AddMediaVolume(-1, showUI); //現在の音量-1
vol = AndroidPlugin.SetMediaVolume(0, showUI); //ミュート:音量=0
#endif

●プラグイン内の対応する Java コード
import android.media.AudioManager;

//現在音量の取得
AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
return audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

//現在音量の設定
AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, showUI ? AudioManager.FLAG_SHOW_UI : 0);

 これは端末のハードウェア音量(メディア音量のみ)を操作するメソッドである。BlueToothコントローラなどでも音量操作できるものは多いので、Cardboard/ハコスコVRアプリなどに実装すると便利かも知れない(Cardboard アプリを Unity5.6.3p1 以前でビルドした場合ハードウェア音量キーが無効になるので。Unity5.6.3p2 以降だとハードウェア音量キーが効く→UIが出る)。

 引数の showUI は音量操作をしたとき、端末上のUIを表示するか否かのフラグである。VRアプリでは非表示にして自前でUIを実装した方が良いだろう(端末のUIは2眼にはならないので)。元々そのために作ったものである(笑)。

 またちょっとしたことだが、ネイティブ呼び出しは非常に負荷が高い動作なので、最大音量(GetMediaMaxVolume())など通常途中で変わらないものは、値をキャッシュして利用する仕組みなどを作った方が良いだろう。こういう手法を常にやるクセを付けておくと高速な処理が書けるようになる(※ただしネイティブ関連のオブジェクトはアプリが落ちたときのことを考慮して、あまりキャッシュしない方が良いかも知れない。またある程度JNIが高速化してくれているらしい。マニュアル参照)。

(参考)Unity で Java プラグインを 使用する上でのヒント

 同梱されているハードウェア音量操作をするプレファブとスクリプト「HardVolumeController」の詳細は以下の記事にまとめて置いたので、必要あればそちらも参照して欲しい。

【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする

 サンプルコードは「Assets/FantomLib/Scripts/Module/HardVolumeController.cs」の「VolumeUp()」「VolumeDown()」「VolumeMute()」「VolumeNow()」「volume プロパティ」「maxVolume プロパティ」あたりを見て欲しい。またプレファブ「Assets/FantomLib/Prefabs/System/HardVolumeControllerWithToast」にはトースト(Toast)で操作したときの音量を表示できるようにセットアップしてある(デモに使っているものと同じ)。少し改造すればVRにも応用できるだろう。



■ハードウェア音量操作のイベントを取得する [メディア音量のみ]


●Unity で Android のハードウェア音量操作のイベントを取得する(メディア音量のみ)
using FantomLib;

void OnEnable()
{
#if UNITY_ANDROID && !UNITY_EDITOR
//ハードウェア音量キーのリスナー登録
AndroidPlugin.HardKey.SetKeyVolumeUpListener(gameObject.name, "HardVolumeKeyChange", "VolumeUp");
AndroidPlugin.HardKey.SetKeyVolumeDownListener(gameObject.name, "HardVolumeKeyChange", "VolumeDown");
#endif
}

void OnDisable()
{
#if UNITY_ANDROID && !UNITY_EDITOR
//ハードウェア音量キーの全リスナー解除
AndroidPlugin.HardKey.RemoveAllListeners();
#endif
}

//ハードウェア音量キーのイベントハンドラ(Android ネイティブから呼ばれる)
void HardVolumeKeyChange(string message)
{
if (message == "VolumeUp")
{
if (OnHardVolumeKeyUp != null)
OnHardVolumeKeyUp.Invoke();
}
else if (message == "VolumeDown")
{
if (OnHardVolumeKeyDown != null)
OnHardVolumeKeyDown.Invoke();
}
}

●プラグイン内の対応する Java コード
import android.view.KeyEvent;
import com.unity3d.player.UnityPlayerActivity;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

public class HardVolKeyOnUnityPlayerActivity extends UnityPlayerActivity {
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP: //音量大キー
UnitySendMessage(callbackGameObjectUp, callbackMethodUp, returnValueUp);
break;
case KeyEvent.KEYCODE_VOLUME_DOWN: //音量小キー
UnitySendMessage(callbackGameObjectDown, callbackMethodDown, returnValueDown);
break;
}
return super.onKeyDown(keyCode, event);
}
}

 これは端末のハードウェア音量(メディア音量のみ)を操作したとき、Android → Unity へイベントメッセージを送るためのリスナー登録メソッドである。このリスナーの実装は「HardVolKeyOnUnityPlayerActivity」に書かれていて、簡単に言えばアクティビティのUIスレッドからイベントを検知したら Unity へ知らせるだけのものである。そのために元の「UnityPlayerActivity」(デフォルトでAndroidビルドで使用されている)をオーバーライドして使う必要がある(マニフェストファイルの「-HardVolKey」が付いているものに設定されている)

 受け取ったイベントは Unity 側で更に「OnHardVolumeKeyUp」「OnHardVolumeKeyDown」でコールバックされるが、これはインスペクタで登録できるようにしてあるので、元々ハードウェア音量キーが有効なアプリでは表示するメソッド(VolumeNow() 等)を登録し、VR(Cardboard/ハコスコ)など元はハードウェアキーが無効になっているアプリでは音量増減メソッド(VolumeUp()/VolumeDown())を登録すれば良い(Unity5.6.3p1 以前でビルドした場合。Unity5.6.3p2 以降だとハードウェア音量キーが効く→UIが出る。※どうやらバグだったらしい。Unity5.6.3p2のリリースノートにFixされたとあった。しかしかえってUIが出るのは良くない(笑))。VRでは2眼になるので showUI はオフにして、自前でUIを実装した方が良いだろう。

 同梱されているハードウェア音量操作をするプレファブとスクリプト「HardVolumeController」の詳細は以下の記事にまとめて置いたので、必要あればそちらも参照して欲しい。

【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする

 サンプルコードは「Assets/FantomLib/Scripts/Module/HardVolumeController.cs」の「OnEnable()」「OnDisable()」「HardVolumeKeyChange()」あたりを見て欲しい。またプレファブ「Assets/FantomLib/Prefabs/System/HardVolumeControllerWithToast」にはトースト(Toast)で操作したときの音量を表示できるようにセットアップしてある(デモに使っているものと同じ)。少し改造すればVR(Cardboard/ハコスコ)にも応用できるだろう(→「UnityChan Flyer」と「SapphiartChan Live Show!」の音量操作にはこのプラグインを使って uGUI で実装している)。

(実際に動作確認した機器)





■更新履歴

17/10/01(新規リリース)
トースト(Toast)
Yes/Noダイアログ(AlertDialog)
OKダイアログ(AlertDialog)
通知(Notification)
任意のURIに対するアクション
音声認識(SpeechRecognizer)
ハードウェア音量操作
17/10/28(機能追加・一部修正)
・[追加]選択ダイアログ(単一/複数:AlertDialog/SingleChoice/MultiChoice)
・[追加]テキスト読み上げ(TextToSpeech)
・[修正]音声認識の戻り値の区切り文字(改行("\n"))が最後に付かないようにした(Split('\n')で分割しやすくするため)。
17/11/03(機能追加)
・[追加]テキスト入力ダイアログ(単一行/複数行)
17/11/06(機能追加)
・[追加]選択ダイアログ(単一/複数:AlertDialog/SingleChoice/MultiChoice)の各アイテムごとに戻り値を指定できるオーバーロードを追加。
17/11/10(機能追加・一部修正)
・[追加]数値/半角英数/パスワード入力のテキストダイアログを追加。
・[追加]テキスト入力ダイアログ(単一行/複数行)にメッセージを入れるオーバーロードを追加。
・[修正]テキスト入力ダイアログ(単一行/複数行)の初期値にも文字数制限がかかるように修正。
・[修正]テキスト入力ダイアログ(単一行/複数行)が表示されたときに全選択とソフトキーボードが出るようにした。
17/11/16(機能追加)
・[追加]日付/時刻選択ダイアログを追加。
・[追加]チェックボックス付きのダイアログ(Yes/No, OK)を追加。
・[追加]Android の色形式(int値:ARGB)と Unity の Color 形式の相互変換「XColor」クラスをライブラリとして追加。
17/11/22(機能追加)
・[追加]スイッチダイアログを追加。
・[追加]スライダーダイアログを追加。
・[追加]真偽値、オブジェクト(クラス・構造体)、配列、リスト、辞書、キー&値ペアを保存する「XPlayerPrefs」クラスをライブラリとして追加。
17/12/03(機能追加)
・[追加]カスタムダイアログを追加。
・[追加]パラメタを簡単に扱うための辞書ラッパー「Param」クラスをライブラリとして追加。
・[追加]ハードウェアキーによる端末自身での音量操作可否メソッド(SetVolumeOperation())を追加。
17/12/16(一部修正)
・[修正]XColor の RedValue(Color), GreenValue(Color), BlueValue(Color), AlphaValue(Color), ToIntARGB(Color) の処理を計算式に変更。
18/01/09(機能追加・一部修正) [アセットストア版:ver.1.1]
・[追加]ピンチスワイプ(フリック)長押し(ロングタップ)をライブラリとして追加(デモシーン: PinchSwipeTest も追加)。
・[追加]モバイル操作にも対応したカメラスクリプト(SmoothFollow3)をライブラリとして追加。
・[修正]XDebug(ランタイム時の Debug.Log 表示スクリプト)に行数制限機能を追加。
18/01/18(一部修正)
・[修正]複数選択ダイアログの初期値が無視されていた不具合を修正。
18/02/03(機能追加・一部修正) [アセットストア版:ver.1.2]
・[追加]おおよそ全ての機能のプレファブ&「~Controller」スクリプトを追加。
・[追加]単一選択(SingleChoiceDialog)複数選択(MultiChoiceDialog)スイッチダイアログ(SwitchDialog)カスタムダイアログのアイテムに値変化のコールバックを追加。
・[修正]XDebug の自動改行フラグ(newline)が無視されていた不具合を修正。また、行数制限を使用しているときに、OnDestory() でテキストのバッファ(Queue)をクリアするようにした。
18/02/15(機能追加) [アセットストア版:ver.1.3]
・[追加]WIFIのシステム設定を開く機能を追加。
・[追加]Bluetoothの接続要求(ダイアログ表示)をする機能を追加。
・[追加]アプリChooserを利用してテキストを送信する(簡易シェア)機能を追加。
・[追加]ストレージアクセスフレームワーク(API19以上)を利用して、テキストファイルの保存と読み込み機能を追加。
・[追加]ギャラリーアプリを起動して、画像ファイルのパスを取得する機能を追加(サンプルとしてテクスチャへのロードとスクリーンショットを追加)。
・[追加]ファイルパスをMediaScannerに登録(更新)する機能を追加。
18/02/19(機能追加・一部修正) [アセットストア版:ver.1.4]
・[追加]バイブレーター(振動)機能(StartVibrator())を追加。
・[追加]通知(Notification)にもバイブレーター(振動)機能のオーバーロードを追加。
・[修正]全ての拡張エディタスクリプトを「SerializedProperty」に置き換え(エディタ上で設定が保存されないことがあったので)。
18/02/25(機能追加) [アセットストア版:ver.1.5]
・[追加]バッテリーの温度、コンディション(オーバーヒート、良好、等)、残量、接続状態のステータス取得(リスニング)を追加。
18/03/16(機能追加) [アセットストア版:ver.1.6]
・[追加]デバイスの回転のイベント取得を追加。
・[追加]おおよそ全てのセンサーの値取得機能を追加(※センサーのサポート自体は端末のモデルに依ります)。
18/03/21(機能追加) [アセットストア版:ver.1.7]
・[追加]各システム設定画面を開くプレファブとデモを追加。
・[追加]AndroidActionControllerに「ActionType.ActionOnly」とアクションの入力支援機能を追加。
・[追加]MailerController, DialerController 等、専用のアクションコントローラをいくつか追加。
18/03/26(機能追加) [アセットストア版:ver.1.8]
・[追加]デバイス認証(指紋・パターン・PIN・パスワード等。ユーザーの設定による)の利用機能を追加。
・[追加]実行中デバイスの API Level(int型)の取得機能を追加。
18/04/04(機能追加・修正) [アセットストア版:ver.1.9]
・[追加]パーミッション付与のチェック(AndroidPlugin.CheckPermission(), ~Controller.IsPermissionGranted)機能を追加。
・[修正]いくつかの「~Controller」[*] に、起動時(Start())にサポートのチェック(IsSupported~)とパーミッションの付与チェック(IsPermissionGranted)を追加。不可のとき「OnError」コールバックにエラーメッセージを返すようにした。
18/04/08(機能追加) [アセットストア版:ver.1.10]
・[追加]QRコード(バーコード)スキャナを起動しテキストを取得する(ShowQRCodeScanner())機能を追加。
・[追加]センサー値の一般的な定数(SensorConstant)を追加。
18/04/10(機能追加・修正) [アセットストア版:ver.1.11]
・[追加]StartAction(), StartActionWithChooser(), StartActionURI() に複数パラメタオーバーロードを追加。AndroidActionController も複数パラメタ対応。
・[修正]MailerController を複数パラメタアクションに変更(より多くのメーラーが対応できるため)。
・[追加]マーケット(Google Play)検索機能を追加(MarketSearchController)。
・[追加]アプリのインストールチェック(IsExistApplication())、アプリ名(GetApplicationName())、アプリバージョン番号(GetVersionCode())、アプリバージョン名(GetVersionName())の取得機能を追加。



■ユニティちゃんと音声認識でじゃんけん(Android 版)

 せっかくなので、このプラグインを使って音声認識でじゃんけんゲームを作ってみた。音声認識の箇所はパッケージに入っている「Assets/_Test/Scripts/SpeechRecognizerTest.cs」をほぼそのまま使っている。具体的には、受け取った結果は改行("\n")で連結されてくるのでそれを分割し、それらの最初の1文字でグー、チョキ、パーを判定する処理(いくつか候補をデータ化してある)を追加しただけだ。

(※) Unity 2017.1.1f1 / Windows10(x64) でビルド。Galaxy S7 Edge (Android 7.0) で確認。

デモアプリのダウンロード (Google Drive を利用)


Android 4.2以上
※「提供元不明アプリのインストール」許可が必要です。


 じゃんけん自体のアルゴリズム・作成方法を知りたければ以下の書籍を参考にすると良いだろう。アイコンがそっくりなのは、実際にこの本を以前読んでいたためである(笑)(※アプリ内のアイコンは新たに作ったものです)。また音声認識は以下の本も参考にしている(※ただし少し古い。実際のビルドは AndroidStudio 2.3.3 でやった)。なのでこのサンプルは2つをミックスしただけとも言える(笑)。

(じゃんけん画像素材)
LiveMaker 指南番

(じゃんけんゲーム/音声認識 参考)




 実際の Java コードは色々値をチェックしたり条件分岐したり、高速化のためにキャッシュしたり、StringBuilderを使ったりしているが、長くなるのでここでは簡略化したものを書いてあると考えて欲しい。Java を知っている人なら中身は非常に簡単なものばかりだとわかるだろう。AndroidStudio を使ったことあるなら AAR プラグインをビルドするのは簡単なので、挑戦してみるのも良いかも知れない。以下に参考資料を載せておこう。この2つの記事で基本的なプラグイン作成方法は十分だ(→実際にこれらプラグインはそのまんまの方法で作った(笑)。※AndroidStudio 2.3.3 でビルド)。

(参考)
Unity : Androidプラグインを作る一番簡単な方法
AndroidプラグインからUnityの関数を呼び出す - UnitySendMessage


(関連記事)
【Unity】標準以外のセンサー(歩数計や心拍数など)を使う(Android)
【Unity】AssetStore版 FantomPlugin のセットアップ
【Unity】標準以外のセンサー(歩数計や心拍数など)を使う(Android)
【Unity】カスタムダイアログを簡単に生成するプレファブを作ってみた(CustomDialogController)
【Unity】Androidでカスタマイズしたダイアログを動的生成できるプラグインを作ってみた
【Unity】Androidでスライダーで設定を変更するダイアログを使う
【Unity】Androidでスイッチで設定を変更するダイアログを使う
【Unity】Androidの選択ダイアログを使う
【Unity】Androidで日付・時刻選択ダイアログ(DatePicker, TimePicker)を使う
【Unity】Androidで数値・半角英数・パスワード入力ダイアログを使う
【Unity】Androidでチェックボックス付きのアラートダイアログ(AlertDialog)を使う
【Unity】Androidでテキスト入力ダイアログを使う
【Unity】Androidのテキスト読み上げ(TextToSpeech)を使う
【Unity】Androidで音声認識を使う
【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする
【Android】【Java】音声入力(音声認識)で文字列を取得する
【Android】【Java】AlertDialog を使ってみる


このコンテンツの一部には『ユニティちゃんライセンス』で許諾されたアセットが使用されています。
Portions of this work are licensed under Unity-Chan License



category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  Unityプラグイン  Cardboard  VR  ユニティちゃん  音声認識 
tb: 0   cm: --

【Unity】Amazonアプリストアに申請する  


 今度は Unity で「Google Cardboard/ハコスコ」で楽しめるスマホ用VRアプリをビルドしてAmazon AppStore に申請してみた。というより先日 Oculus Store に申請した GearVR アプリは、元々 Cardboard 用に作ったアプリだったので、こちらも試しにアップしてみるのも良いかと思っただけだったりする(てゆか最近まで個人でも Amazon AppStore から配信できることを知らんかった(笑))。

 やってみた感想は、たぶんこれまでで一番簡単だった。バイナリ(apk)のチェックなどは完全自動化されているようだし、そもそもアプリ動作に対する要件が特にないので(例えば「バックボタンで終了しろ」みたいな)、画像を揃えるだけで申請できた。また Google Play で公開されているものをそのまま使っても良いようなので(ただし、Google の API は使えないので、Amazon の API に入れ替える必要あり)、既にアプリ公開している人でもリーチを広げるのには良いかも知れない。デベロッパー登録から申請まで全て無料でできるので試してみるのも一興かと(笑)。



(※) Unity 5.6.2p3 / Windows10(x64) で確認



■Amazon AppStore 申請の大まかな流れ

 まずは既存の apk があるのなら、デベロッパーサイトにある「テストを始める」にその apk ファイルをドラッグ&ドロップしてみるのも良いかも知れない。申請時にも同じように apk をアップロードできる画面があるが、ここにドロップした場合は、デベロッパー登録なしでもテストできる。問題がなければ、そのまま申請の手続きの画面に移ることも可能だ(結果の履歴から申請登録することもできる)。


 デベロッパー登録がまだならアカウントを作成する必要があるが、それが完了したら即申請もできる。以下に簡単な申請までの流れを書いておこう。


1.デベロッパー登録をする。税に関する情報入力(課金アプリにする場合や広告などを使うときの税徴収に関する電子公文書)は少し面倒だが、無料にする場合も必要らしい。認証は小一時間もすれば完了する。

2.デベロッパーサイトの「ダッシュボード」または「アプリ&サービス」の「新規アプリを追加」でアプリを登録できる。アプリの情報入力および画像アセット、バイナリ(apk)をアップロードする。また、ドラッグ&ドロップのテストをした場合は結果の履歴が残っているので、そこから登録もできる(最新版は一番上)。

3.自動チェック(画像アセットが揃っている、アプリの問題チェック通過)が済んだら、Amazon AppStore に申請する(すべてが完了したら「アプリを申請」が押せるようになる)。

4.申請後はしばらく審査待ちになる(最大1週間とあるが、早ければ1日でリリースできる)。

5.審査をパスしたら、今度はリリース待ちになる(リリース日は情報入力で設定した日。未入力なら審査パス後にすぐ)。


 ちなみに私の場合、リリース日は特に指定しなかったせいもあり、約6時間後にはリリースされていた。はやっ!



■Amazon AppStore 申請要件の概要(主に画像アセット)

 ここでは必要なアセット(主にストア用画像)をまとめておく。細かい内容は FAQ に書かれているので、簡単に目を通しておくと良いだろう。

●提出するアセットの仕様(※画像のサイズなど)

・小アイコン:114 x 114px PNG (背景色透明)(アプリをインストールした後、端末に表示されるアイコン)

・大アイコン(サムネイル):512 x 512px PNG (背景色透明)(アイコンと同一の画像であること)

・スクリーンショット:3~10 枚まで:PNG または JPG。使用できるサイズは、
 800 x 480px (5:3), 1024 x 600px (128:75), 1280 x 720px (16:9), 1280 x 800px (8:5),
 1920 x 1080px (16:9), 1920 x 1200px (8:5), 2560 x 1600px (8:5)
 のいずれか(縦長または横長)

・プロモーション用画像 (推奨):1024 x 500px (256:125) (横長のみ) PNG or JPG

・動画:最大5 MPEG-2, WMV, MOV, FLV, AVI, H.264 MPEG-4
 最小幅720px (4:3 or 16:9); 高さ1200 kbps以上

(実際例)

(c) UTJ/UCL

(参考)
アプリの申請:アプリの詳細



■アプリの Build Settings

 Amazon AppStore にはあまり技術的な要件はないみたいだが、一応今回のビルド設定も載せておこう。ここでは Cardboard アプリを例にしているが、基本的に普通のアプリでも変わらないので、特に気をつける部分は API Level や CPU の設定くらいかも知れない。実際には申請時の登録情報にサポートしている端末を選択することができるので、既存のままでもかまわない。Fire タブレットなどにも対応させるなら「Android 5.1 Lollipop API Level 22」あたりにしておけば良いらしい(持ってないので未実証だが、アプリテストを信頼するとして(笑))。


 あとはテクスチャの圧縮を使うなら「OpenGL ES」のバージョンくらいか。「OpenGL ES 2.0」なら間違いないが、「OpenGL ES 3.0」なら「Android 4.3 (API level 18)」以上を、「OpenGL ES 3.1」なら「Android 5.0 (API level 21)」にしておく必要がある。以下にいくつか参考URLを載せておこう。

(参考)
Android プラットフォームのバージョン
OpenGL ES
Unityで画像fを圧縮する際のフォーマットのお話し(ASTCとETC)




 「Quarity Settings」なども任意で良いが、私は GearVR の設定のときと同じものを使っている。パフォーマンスが許すなら「Anti Aliasing」(アンチエイリアス処理)を「2x MultiSampling」以上にしても良いだろう。モバイルの場合、警告「Warning! Using antialiasing on a mobile device may decrease performance severely. You can change the mobile quality settings in 'Project Settings -> Quality Settings'.」(モバイルではアンチエイリアス使うとパフォーマンス下がるよ)が出るが、Android 5.0 (API 21) 以上ならわりといけるようだ。




■アプリのアップデート

 一番簡単な方法は申請の流れのときと同じように「テストをはじめる」に新しいバージョンのアプリをドロップし、「Test Results available」が出たら「View Results」(or 結果を表示)をクリックし、テストの履歴から「AppStore に提出」を押すことだろうか。提出ボタンを押すと「アプリには既にバイナリが含まれています。バイナリを置き換えますか?」とダイアログが出るが「YES」を押し、登録を保存すれば良い。あとは既存の情報を編集したり、リリースノートを書けば申請できるようになる。





 これははじめ戸惑ったのだが、メニューの「次バージョン」を押しても同じ画面になるが、「保存してバイナリを追加」は「既存をそのまま+新しいのを追加」のようになってしまうようだ。また、なぜかバイナリ(binary2)の自動チェックがされず、サポート端末が未設定になる。「バイナリを削除→追加」でも良いかもしれないが、先に述べたテスト結果からそのまま置き換え→提出した方が楽だ。


(関連記事)
【Unity】GearVR アプリを Oculus Store に申請する(要件・仕様の概要)
【Unity】GearVR 用にビルドする


■VR関連参考書籍・動作確認機器


このコンテンツの一部には『ユニティちゃんライセンス』で許諾されたアセットが使用されています。
Portions of this work are licensed under Unity-Chan License

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: ストア申請  Cardboard  VR  ユニティちゃん 
tb: 0   cm: --

【Unity】VRレーザーポインター(ビーム)を作る  


 あくまで一例だが、簡単なレーザーポインター(ビーム)の実装方法を書いておこう。これは実際に私の作ったアプリに使っているものと同じだ。フリーなのでインストして試してみるのも良いだろう。

※Oculus Store で配信中(検索:sapphiart)

 はじめに大まかに仕様的なものを説明しておくと、今回の実装方法は「レーザーの発射位置(Anchor)から指している位置(Target)に向かってラインレンダラ(Line Renderer)で線を引く」という非常に簡単なものである(笑)。なので例として GearVR コントローラを使っているが、たぶん他のコントローラでも移植はそう難しくはないだろう。また SDK 依存を減らすためにも、レーザーを描く部分とそれを SDK(ここでは Unity 公式の VRSample)で使う部分を分けて書いておいた。レーザーで指すだけという最低限の機能しか付けてないが、コードの内容を理解すれば、他の SDK やコントローラでも簡単に応用できるだろう。

 また、今回は Oculus Utilities 1.16.0-beta を使用することにおいて、Unity2017.1f03 でやってみたら色々エラーが出るようなので、Unity 5.6.2p3 を使っている。なので自力で修正、または今後のバージョンアップで修正されたのなら、細かい仕様が変わってしまっている恐れがあるので、適宜置き換えて考えて欲しい。


(※) Unity 5.6.2p3 / Windows10(x64) で確認



■レーザー(ビーム)ポインタをラインレンダラで描く

using UnityEngine;

/// <summary>
/// LineRenderer によるレーザーポインタ
/// 2017/8/21 Fantom (Unity 5.6.2p3)
/// http://fantom1x.blog130.fc2.com/blog-entry-259.html
///(使い方)
///・空の GameObject にアタッチし、LineRenderer を追加する(線の幅[Width:0.005くらい]やマテリアル・色も設定する)。
///※LineRenderer のマテリアルを「Sprites-Default」などアルファが利くものにし、色のアルファを設定すれば半透明レーザーにできる。
///※Use World Space は true である必要がある(デフォルト値)。
///・インスペクタで Anchor にコントローラなどの GameObject をセットする。
///・認識させるオブジェクトにコライダを追加する。
///(仕様説明)
///・anchor → target へ LineRenderer で線(レーザー)を引く。
///・LineRenderer は厚さのないテープのようなものなので(ただし常にカメラの方を向いている)、カメラ位置とanchorが同じで、targetが真正面方向だと見えない(故にanchorのY軸をずらせば見える)。
///・外部の Raycaster で判定をするときは shotRay をオフにして、target に指す位置を入れる。
///・shotRay がオンのときは anchor 位置から anchor.forward 方向へ Ray を飛ばし、ヒットしたオブジェクトの transform が target に入る(ヒットが無いときは null)。ヒットした位置ではないことに注意(ヒットした位置は RaycastHit.point で取得できる)。
/// </summary>
public class LaserPointer : MonoBehaviour
{
public bool IsActive = true; //稼働フラグ
public float defaultLength = 0.5f; //ヒットなしのときのレーザーの長さ

public bool shotRay = true; //Ray を撃つ(false のときは target に指す位置を入れる)
public float rayLength = 500f; //Ray の長さ
public LayerMask rayExclusionLayers; //Ray 判定を除外するレイヤー

public Transform target; //指す位置(shotRay=true のときはヒットしたオブジェクトの transform が入る)
public Transform anchor; //発射位置(コントローラの位置)
public LineRenderer lineRenderer; //レーザーを描画するラインレンダラ

// Use this for initialization
void Awake()
{
if (lineRenderer == null)
lineRenderer = GetComponent<LineRenderer>();
}

// Update is called once per frame
void Update()
{
if (!IsActive)
{
lineRenderer.enabled = false;
return;
}

if (shotRay)
{
Ray ray = new Ray(anchor.position, anchor.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, rayLength, ~rayExclusionLayers))
{
target = hit.transform;
DrawTo(hit.point); //ヒットした位置にしたいため
return;
}

target = null;
}

if (target != null)
DrawTo(target.position);
else
DrawTo(anchor.position + anchor.forward * defaultLength); //コントローラの正面方向へ一定の長さ
}

//レーザーを描く
void DrawTo(Vector3 pos)
{
lineRenderer.enabled = true;
lineRenderer.SetPosition(0, anchor.position);
lineRenderer.SetPosition(1, pos);
}
}

 使い方は空の GameObject にこのスクリプトをアタッチし、更に「Line Renderer」を追加する(インスペクタの一番下にある「Add Component で「LineRenderer」を入力すると楽)。Line Renderer を追加したら、インスペクタで線の幅(Width)を 0.005 くらいにしておくと良い。またマテリアル・色はデフォルトでも構わないが、半透明レーザーにしたいなら、アルファの効くマテリアル(例えば「Sprites-Default」など)にし、色の設定でアルファを 200 くらいにしておくと良いだろう。線の太さの変化やグラデーション変化を加えても良い。これらは任意で構わない。ただし「Use World Space」(位置指定を World Space にする)だけは true にしておく必要がある(デフォルトでは true になっている)。

 あとはインスペクタで「Laser Pointer」の「Anchor」にコントローラなどレーザーを発射するオブジェクトをヒエラルキーからドラッグ&ドロップなどでセットするだけだ。


 オブジェクトの判定方法はコントローラから前方に Ray を飛ばして、ヒットしたオブジェクトを取得するだけのもので(target にその transform が入る)、特に何の機能も付いてない。レンスポンスなどは何らかの SDK などを使用することになるだろう。なお、ヒットさせたいオブジェクトにはコライダがアタッチされてる必要がある。

 1つ注意点としては、Line Renderer は厚さのないテープのようなものなので(ただし常にカメラの方を向いている)、カメラ位置とレーザー発射位置(Anchor)が同じで、かつ指す位置(Target)が真正面方向だと Gameビューでは見えないことだ。要するにエディタ上で初期位置がすべて (0, 0, 0) のようになってると見えないので、デバッグ用に表示したいなら、コントローラ等のY軸をずらせば見えるようになる(Sceneビューでは角度を変えれば見える)。実機ではコントローラは普通見下ろす感じになるので、初期位置が(0, 0, 0) でも特に問題はない(手の位置と連動して Transform が変わる)。



■GearVR コントローラでレーザーポインタを使う

 では具体的に Oculus Utilites(掲載時点:v1.16.0-beta) を使って、GearVR コントローラでレーザーポインタを使う方法をやってみよう。Oculus Utilites 自体のインポートからはじめるなら「GearVR ビルドをする」の記事を参照して欲しい。

 サンプルとしてシーン「Assets/OVR/Scenes/GearVrControllerTest」を開いてみよう。複製したものを使っても良い。このサンプルはビルドすればそのまま GearVR コントローラが使えるが、このコントローラからレーザーが出るようにする。設定は前述したインスペクタのようにすれば良い。とりあえず右手のコントローラを「Laser Pointer」の「Anchor」にセットしよう。ヒエラルキーとインスペクタでは以下のような感じになる。


 セットアップが済んだら、あとは「GearVR ビルドをする」と同じように「Build Settings」でこのシーンを追加して apk を出力するだけだ。実機で動作を確認してみよう。
●サンプルにレーザーが追加される
(※) Galaxy S7 Edge で確認



■VRStandardAssets(VRSamples)を使ってレーザーポインタでアイテムをクリックする

 次に何らかの SDK を使ってレーザーポインタでインタラクティブな動作をやってみよう。今回は公式の VRSamples を使うことにする(※VRSamples は完成プロジェクトなので、インポートすると現在のプロジェクトを書き換えてしまうので注意。別の新規プロジェクトにインポートする方が良い)。と言ってもレティクル(視点ポインタ)などのUIや Raycast でのオブジェクトの判定は他の SDK でも同じようにあるハズなので、一部置き換えれば移植は簡単だと思う。

●VRStandardAssets(VRSamples)でレーザーポインタを使う
using UnityEngine;

namespace VRStandardAssets.Utils
{
/// <summary>
/// VRSample の VREyeRaycaster や Reticle(使用するのはUIの位置)を LaserPointer.target に入力する。
/// </summary>
public class VRLaserPointer : MonoBehaviour
{
public LaserPointer laserPointer; //レーザーの描画
public VREyeRaycaster eyeRaycaster; //Rayを発射してオブジェクトを判定する
public Transform guiReticle; //レティクルなどのUI

// Update is called once per frame
void Update()
{
if (eyeRaycaster.CurrentInteractible != null)
laserPointer.target = guiReticle;
else
laserPointer.target = null;
}
}
}

 これは VRStandardAssets(VRSamples) の機能を前述の「LaserPointer」に橋渡しするだけのスクリプトである。VRStandardAssets では「VREyeRaycaster」というスクリプトが Ray を発射し、「VRInteractiveItem」コンポーネントとコライダを持つオブジェクトを取得するという仕組みでインタラクティブ機能を実現している。VRStandardAssets に入っているプレファブの一部を利用して、ここまでのサンプルシーン「GearVrControllerTest」で、レティクル付きのレーザーポインタでオブジェクトをクリックできるように改造してみよう。少し面倒だが、以下の手順でセットアップしたものをプレファブ化しておけば使い回しも簡単にできる。


1.「Assets/VRSampleScenes/Prefabs/Utils/」にある「MainCamera」をヒエラルキーにドラッグ&ドロップしよう。ドロップしたらカメラ自体は元からある「OVRCameraRig」を使うので、カメラとその他必要ないコンポーネントを削除(Remove Component)する。具体的には「Camera」「GUI Layer」「Flare Layer」「Audio Listener」「VR Camera Fade」「Return To Main Menu」「VR Tracking Reset」を削除する。残ったのは「VR Eye Raycaster」「VR Input」「VR Camera UI」「Selection Radial」「Reticle」となるようにする。また「MainCamera」のタグを無くし、ついでに名前を変えておこう。ここでは「VR Eye」としている。あとヒエラルキーで「Fade Panel」も削除しておこう。


2.次に先に作った「LaserPointer」オブジェクトに「VRLaserPointer」をアタッチしよう。そしたらヒエラルキーからドラッグ&ドロップして図のようにセットアップする。「Shot Ray」をオフにするのを忘れずに。これで「VREyeRaycaster」に判定を任せ、ヒットしているときレティクルのUI までレーザーが引かれるようになる(ヒットしてないときは「Default Length」の長さになる)。


3.それとレティクル(視点ポインタUI)もセットアップしておく。ヒエラルキーで「VR Eye>VRCameraUI>GUIReticle」を展開して、「Image」をオンにし、「Color」をレーザーに合うように色を変更しておこう。また今回は使用しないが、必要なら更に展開して UISelectionBar(リングUI)の色も変えておいても良い。ここではリングUI は起動時には非表示にしたいので「VR Eye」に戻り「Selection Radial」の「Hide On Start」をオンにしておく。



※リングUI は起動時に非表示にする


4.「VR Eye」のセットアップができたら、このオブジェクトに先に作った「LaserPointer」オブジェクトをドラッグ&ドロップし、子要素にしよう。そしてこれをプロジェクトエクスプローラでプレファブ化しておく。


5.「VR Eye」のプレファブ化ができたら、ヒエラルキーにあるものとプレファブのものをそれぞれ「RightHandAnchor」「LeftHandAnchor」を展開した先にある「Model」(コントローラの3Dモデル)の子要素に配置しよう。ここに置いておくと、右手用・左手用コントローラを切り替えたとき、自動的にオン・オフされるので便利だ。またプレファブ化した方はヒエラルキー上の参照は外れてしまうので、「Laser Pointer」の「Anchor」だけ設定しておこう。ここでは左手用「LeftHandAnchor」以下にプレファブ化した「VREye」を子要素に置いたので、「Anchor」に「LeftHandAnchor」を設定している。また子要素にすると Transform の Position が再計算されるので、(0, 0, 0) になっていることを確かめよう。ずれてしまった場合は必ず修正する(※動作は正しくても見た目がおかしくなるため)。あと情報表示が邪魔なら「CenterEyeAnchor」以下の「Canvas」を消しても良い。



※Transform は必ず (0, 0, 0) にする


6.これで必要なセットアップは一通り完了したので一旦シーンを保存しよう。またヒエラルキーの「OVRCameraRig」を「OVRCameraRig Gear」とでもしてプレファブ化しておくと再利用が簡単になる。そしてインタラクティブなテストをするために「VRSamples」に入っているサンプルシーン「Assets/VRSampleScenes/Scenes/Examples/InteractiveItem」を開き、ヒエラルキーにある「Cube1」をプレファブ化しよう(3つあるがどれでも同じ)。プレファブ化したらシーンは閉じてしまって良いので(保存はしなくても良い:任意)、再びテストするシーン「Assets/OVR/Scenes/GearVrControllerTest」に戻って、ここに先ほどプレファブ化したインタラクティブなアイテム「Cube1」をいくつか置いておく。


7.最後にシーンを GearVR 用にビルドしてみよう(VRSamples をあとから追加インポートした場合はシーンがいくつか追加されているので全て削除し「GearVrControllerTest」だけビルドする)。レーザーポインタでオブジェクトを指したり、クリックしたりすると色が変化するハズだ(起動初期にコントローラが認識されないときは、Backボタンを短押しすると認識される)。これで簡単な機能だけだがとりあえず完成だ。インタラクティブなアイテムにはスクリプト「VRInteractiveItem」の他に「ExampleInteractiveItem」もアタッチされている。この辺りのソースを覗けば(イベントで色を変えてるだけ)、他のアイテムなどにも応用は可能だろう。
●アイテムにヒットしてないときはデフォルトの長さで、ヒットしてるときはレーザーが伸びていく

(※) Galaxy S7 Edge (Android 7.0) で確認


(関連記事)
【Unity】GearVR アプリをビルドする
【Unity】GearVR アプリを Oculus Store に申請する


■VR関連参考書籍・動作確認機器




この作品・コンテンツは『サファイアートちゃん ライセンス条項』の元に提供されています。
This work is provided under "SapphiArt-Chan License" agreement.
© SapphiArt inc /SCL

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: GearVR  VR 
tb: 0   cm: --

【Unity】GearVR アプリを Oculus Store に申請する(要件・仕様の概要)  


 せっかくなので試しにビルドした GearVR アプリを Oculus Store に申請してみたのでその記録。GearVR のアプリ申請は公式の Oculus デベロッパーサイトにドキュメントが掲載されているが、基本的に英語なので、google翻訳使いながらやるのは大変だった(笑)。いくつか日本語の pdf などもあったが、内容が少し古くなっていたので、現時点での方法を簡単にまとめておくことにした。今後も色々更新されると思うので、なるべく最新版を検索するようにした方がいいだろう。ちなみにデベロッパー登録から申請まで全て無料でできる。


 今回は「GearVR 用にビルドする」と同じ方法で Android ビルドが成功した状態であることを前提とした申請方法・要件なので、ビルドからやる場合は前回の記事を見て欲しい。内容的には一部被る部分もあるが、ここでは主に公式の Oculus デベロッパーサイトからの最低限必要な部分だけの抜粋を中心に書いていこうと思う。

 また、今回は Oculus Utilities 1.16.0-beta を使用することにおいて、Unity2017.1f03 でやってみたら色々エラーが出るようなので、Unity 5.6.2p3 を使っている。なので自力で修正、または今後のバージョンアップで修正されたのなら、細かい仕様が変わってしまっている恐れがあるので、適宜置き換えて考えて欲しい。


(※) Unity 5.6.2p3 / Windows10(x64) で確認



■GearVR アプリの Oculus Store 申請の大まかな流れ

 古い資料を見ると以前は必要なアセット等をストレージに集めて、サポートにメールなどする必要があったようだが、幸いなことに現在ではデベロッパーサイトで完全に自動化されている。なので、非常に大まかな流れを言えば、以下のようになる。

1.申請用の apk を作成する。

2.デベロッパーサイトの「Manage」(アプリ管理ページ)で必要なアセット(アプリも含む)をアップロードする(※デベロッパー登録が必要:無料)。

3.管理ページでの自動チェック(アセットが揃っている、アプリの自動プレビュー通過)が済んだら、Oculus Team にレビュー申請する(すべてが完了したら「Submit For Review」が押せるようになる)。

4.申請後はしばらく審査待ちになる(編集はロックされる。最大3週間とある)。要件を満たしてない場合、メールでその旨が送られて再度「編集→申請」できるようになる。

5.最終審査をパスしたら、今度はリリース待ちになる(リリース日は後日メールで送られてくる)。

(参考)
Lifecycle of an Oculus VR App

 これらの手順は他のストアなどでもそれほど変わらないと思う。次にその必要な要件(仕様)を簡単にまとめておこう。



■GearVR アプリの Oculus Store 申請要件・仕様の概要

 ここでは仕様的なものの中で重要なものを一覧としてまとめておく。大まかには技術的なものと、必要なアセット(主にストア用画像)があるが、細かい内容は公式ドキュメントや pdf に書かれているので、簡単に目を通しておくと良いだろう。

●技術的な仕様

Android の keystore(署名)がされていること(Unity のデバッグ用は不可)。

「Tools>Oculus>Create store-compatible AndroidManifest.xml」(※掲載時点:Oculus Utilities v1.16.0)で正しく「AndroidManifest.xml」が作成されていること

Back キー(Escape キー)が「0.75秒以上を長押し、それより短い場合は短押し」になっていること。そして長押しのときユニバーサルメニュー(Unity内では何もしなくて良い)、短押しのときは1つ階層(シーン等)を戻る動作、階層ルートでは「Exit to Oculus Home」の確認画面(ダイアログ)を出すこと(Oculus Utilities に入っている「OVRPlatformMenu.cs」を使うなど。自作ダイアログでも動作さえ正しければOK)。

・音量ボタンで大小を操作できること(※Oculus SDK を使っている場合は何もしなくても機能する)。

・ホーム長押しでコントローラのリセンターが機能すること(※Oculus SDK を使っている場合は何もしなくても機能する)。

・スプラッシュ画面は4秒以内(それ以上になる場合は進捗を付ければOK)。

・apk は 500MB 以下。

※他には「スリープに入らないようにする(Unityを使っている分には何もしなくて良い)」「コントローラは左右どちらでも同じように動作」「60fps動作」「発熱停止しないで45分動作」など細かいことも書かれているので一度確認しておこう。しかしこの辺りはベストを尽くせばそれほど厳密ではないっぽい。

(参考)
Gear VR Technical Requirements
Uploading Gear VR Apps


●提出するアセットの仕様(※画像のサイズなど)

(Require:必須)
・Icon : 512x512 px(※背景は透過せず、角丸にしない=正方形のみ)
・Logo Transparent : 360~9000x1440 px(※背景は透過させる)
・Cover Landscape : 2560x1440 px(※下360px がストアのオーバーレイ範囲なので、ロゴを置かない)
・Cover Portrait : 1008x1440 px(※下360px がストアのオーバーレイ範囲なので、ロゴを置かない)
・Cover Square : 1440x1440 px(※下360px がストアのオーバーレイ範囲なので、ロゴを置かない)
・Small Landscape : 1080x360 px [※VR Landscape とも書いてある]
・Hero Art : 3000x900 px (※幅:540+1920+540=3000 px, ロゴを置くときは中央に置く)
・Screen Shots (5枚) : 各 2560x1440 px

(実際例)

(c) UTJ/UCL


(Optional:無くても可)
・Gallery Video : 最小 1280x720 px
└Video Cover Art : 2560x1440 px
・Cubemap : Cubemap - 12,000 x 2000px (※幅:2000x6枚=12000 px [※ツールあり。以下のURL参照])

(参考)
Oculus Store Art Guidelines (pdf)
OVRCubemapCaptureProbe(Oculus Utilities for Unity)
Cubemap Viewer



■提出用 apk をビルドする

 apk の作成については前回の「GearVR 用にビルドする」を見て欲しい。ここでは申請要件・仕様を満たしていることを前提としてアップロードすることとする(満たしていない場合は自動チェックでリジェクトされる)。特に apk について重要な部分は以下のことと考えて良い。

・「AndroidManifest.xml」の属性が正しく設定されているか。
・「Android アプリケーションの署名」が正しく行われているか。

(参考)
Application Manifests for Release Builds

 「AndroidManifest.xml」の属性についてはドキュメントでは細かく指定されているが、Oculus Utilities(※掲載時点:v1.16.0) を使っている分にはメニューから「Tools>Oculus>Create store-compatible AndroidManifest.xml」を実行して自動作成すれば良い。すると「Assets/Plugins/Android/」以下に要件を満たした「AndroidManifest.xml」が作られる。


※ビルドすると警告「No activity found in the manifest with action MAIN and category LAUNCHER.Your application may not start correctly.」が出るが、Oculus Homeから起動するため無視して良い(=端末のランチャーから起動できなくなる)。
※再びデバッグなどで端末のランチャーから起動したい場合は、生成された「AndroidManifest.xml」を削除するか、リネームなどしてビルドすれば、通常起動できるようになる。


 「Android アプリケーションの署名」については、GearVR というより、Androidアプリの仕様なので、公式のドキュメントを参照して欲しい。設定は「Edit>Project Settings>Player」から「Publish Settings」になる。もちろん「Other Settings」内の「Identification>Package Name」はアプリ固有IDとなるので忘れずに(これも Androidアプリの仕様)。

(参考)
アプリの署名

●作成した keystore ファイルとパスワード、エイリアスなどを設定する


●Package Name は世界で唯一のアプリ固有IDとなるので、ドメイン名(任意)も入れるのが良い。




 この他にも「提出用ビルドはOSIGファイルを取り除くこと推奨」とも書いてあるが、実際にはリリース時に自動で削除されるようなので、そのままでも構わない(審査には引っかからない)。



■提出用 apk をアップロード→申請する

 あとは完成した apk や画像アセットなどをデベロッパーサイトにアップロードしよう。管理ページには他にもアプリの説明(ローカライズも含む)や利用規約/プライバシーポリシー、年齢レーティング、価格設定、ソーシャルメディアでのアプリの映像を共有/ストリーミング許可など色々項目があるが、基本的にはすべての項目(Required だけで良い)を入力・設定すれば、Oculus Team へのレビュー申請となる。apk 自体の仕様などはアップロードやプレビューでも自動で判定してくれるが、機能的なもの(Back キーの動作とか)は一度申請してから、要件を満たしていなければリジェクト→修正要項がメールで送られてくる。メールはすべて英語だが、詳しく書かれているので、google翻訳でも使えば十分にわかるハズだ。以下には簡単な手順と概要だけを書いておこう。

1.デベロッパーサイトにログインしたら上部のメニュー「Manage」を押す。

2.はじめての場合は「組織名(Create New Organization)」を聞かれるので入力する(この名前がメーカー名としてストアに表示されるので注意)。

3.管理ページ内にある「Create New App」を押して、「プラットフォーム」「アプリ名(※後で変更できる)」を入力する。完了したら AppID など色々な情報が出るが、ページの上部のアプリ名をクリックすると、進捗が表示されるので「Build」を押せば、apk ファイルをアップロードできる画面になる(初回はページの一番下にある「Upload Build」を押す)。


4.アップロードしたいチャンネルの右にある「…」を押すと「Upload New Binary to ~」が出るのでクリックし、説明が出たら「Choose File」 で apk をアップロードする。


※チャンネルにはアルファ版、ベータ版、テスト版など色々な状態のものをアップロードできるが、最終的には STORE に移すことになるので、はじめてアップロードするときは STORE に直接アップロードしても良い。

5.アップロードしたファイルの自動チェックが終わったら「Continue」ボタンが出るので、他の残りの要項も埋めていく(「Require」だけでも可)。

6.ページに表示されている進捗を見て、すべてが揃ったら Oculus Team に申請する(「Submit For Review」が押せるようになる)。最大3週間かかるとあるが、機能的な要件を満たしてないものはすぐにリジェクトされるので、その場合は修正したビルドを再度アップロード→申請する。

※ちなみに、apk をアップロードした後は実機:GearVR 内の Oculus Home で実際のプレビューを見ることができるようになる。例えば説明の「Short Description」はアプリの詳細から「説明」の項目に表示されていることがわかる。アップロードした画像なども「ギャラリー」の項目を見れば確認できる(ビデオもここで再生できる)。




※Cubemap は試してないが、他のアプリを見るとインストール前に自分の回りの背景が変わるのがあるので(メーカーものは多い)、その背景をアップロードするものだと考えて良い。Oculus Utilities の「Assets/OVR/Prefabs/」にあるプレファブ「OVRCubemapCaptureProbe」をシーンにおいて「F8」キーでキャプチャすることもできるので、試してみるのも良いかも(私は面倒くさかったので提出してない(笑))。

(参考)
OVRCubemapCaptureProbe(Oculus Utilities for Unity)
Cubemap Viewer


 提出し終わったらあとは審査が終わるまで待つしかない(編集はロックされる)。なお、私の場合、年齢レーティング(IARC)の正式な承認(?)(「証明書の恒久的な記録のURL」とメールに書かれている)は約1週間後に送られてきた。Oculus Store の審査自体は1回リジェクト、再申請2日目で審査を通過したが、リリース待ちは13日ほどかかった(土日を含む)。また個人かつ FREE アプリだったので、法人や決済関連があるのならもっと時間はかかるのかも知れない。気長に待つと良いだろう。


(関連記事)
【Unity】GearVR アプリをビルドする
【Unity】VRレーザーポインター(ビーム)を作る


■VR関連参考書籍・動作確認機器



このコンテンツの一部には『ユニティちゃんライセンス』で許諾されたアセットが使用されています。
Portions of this work are licensed under Unity-Chan License


category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: ストア申請  GearVR  VR 
tb: 0   cm: --


プロフィール

Twitter

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop