FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム » Unity »【Unity】Androidでスライダーで設定を変更するダイアログを使う

【Unity】Androidでスライダーで設定を変更するダイアログを使う  


 もう1つ、スイッチのように設定などに使える UI と言ったらスライダー(Android ではシークバー)かな~と思って、試しに今度はスライダーを動的に生成して並べるカスタムダイアログを作ってみた。ついでにゲームなどでは「音楽/ボイス/効果音」の音量設定画面をよく見かけるので、それを模したようなサンプルも作ってみた。設定した音量をセーブ&ロードする機能も付けておいたので、とりあえず Unity-Android で簡単に音量操作を実装しておきたいときなどに良いかも知れない。

 今回も Androidの基本機能を利用するプラグインのアップデート版となる。追加内容・仕様変更などはなるべく更新履歴に書くようにしているが、基本的にはそのまま使えるようにしているので、旧バージョンがある場合は上書きでも構わないと思う。プラグイン自体のセットアップは以前の記事を参照して欲しい。自分で作りたい場合は簡略化したものだが、今回も元の Java コードを書いておくので挑戦してみるのも良いだろう(※Java コードは解説用に一部抜粋・省略したものであって、そのままコピペでは使えないことに注意)。


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


 パッケージに同梱されているサンプルでは、シーン「Assets/_Test/Scenes/DialogExTest」にまとまっているので、適当に複製などして自由に使って欲しい。


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



■スライダーダイアログ(カスタムダイアログ)を使う


●Unity から Android のスライダーダイアログ(カスタムダイアログ)を使う C# コード
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowSliderDialog(title, message, items[], itemKeys[], defValues[], minValues[], maxValues[], digits[], itemsTextColor,
callbackGameObject, resultCallbackMethod, changeCallbackMethod, okCaption, cancelCaption, style);
#endif

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

SeekBar.OnSeekBarChangeListener listener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int i = (int)seekBar.getTag();
values[i] = progress; //※値の変換などは割愛
textViews[i].setText(items[i] + " : " + progress);
UnitySendMessage(callbackGameObject, changeCallbackMethod, itemKeys[i] + "=" + progress);
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};

DialogInterface.OnClickListener oklistener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
String str = "";
for (int i = 0; i < items.length; i++) {
if (i > 0)
str += "\n";

if (itemKeys != null)
str += itemKeys[i] + "=" + values[i];
else
str += values[i];
}
UnitySendMessage(callbackGameObject, callbackMethod, str);
}
}
};

LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

final TextView[] textViews = new TextView[items.length];
for (int i = 0; i < items.length; i++) {
textViews[i] = new TextView(context);
if (itemsTextColor != 0)
textViews[i].setTextColor(itemsTextColor);
layout.addView(textViews[i]);

SeekBar seekBar = new SeekBar(context);
seekBar.setTag(i);
seekBar.setOnSeekBarChangeListener(listener);
layout.addView(seekBar);
}

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

builder.setTitle(title)
.setMessage(message)
.setView(layout.getRootView())
.setPositiveButton(okCaption, oklistener)
.setNegativeButton(cancelCaption, null)
.show();

 これはスライダー(シークバー)を動かすことによって値を変更するカスタムダイアログである。スライダーは Android では SeekBar として実装されていて、内部的にはプログレスバー(ProgressBar:進捗バー)と同じである。なので、進捗の値は整数型(int)になっていて、基本的には正の値を使う前提になっている(0~100% のように)。しかし Unity で使う分には少し不便に感じたので(0.0~1.0f, -128~127 なども扱いたいので)、このプラグイン内では実数型(float)で値を保持するようにした。そのため扱える範囲は整数部分 6 桁+小数点以下 3 桁 までとなっている(引数の digits[] が小数点以下桁数で 0 のとき整数、1~3 のとき 0.1~0.001 のようになる ※下の桁は単純なカット。最後が 0 の場合は表示されない)。平たく言えば -999999.999~999999.999 までと考えても良い(実際には実数型なので使えないわけではないが、整数部分が 7 桁以上になると、"1.0E7"のような表記になってしまうのと、値が大きくなるほど誤差・オーバーフローなどで値が不安定になる ※値チェックはしてない)。まぁ、どのみちダイアログでは表現できる幅は狭いので、適当に 0.0~1.0f の値を 100倍して 0~100(%) で使うとか、ユーザーにとってわかりやすい範囲にする方が良いだろう。

 戻り値は「OK」ボタンを押したとき、キー(itemKeys)が設定されている場合は "key=値" のようにイコール("=")でキーと値のペアが、キーが未設定(itemKeys = null)のときは、値のみが、改行("\n")で結合されて、ヒエラルキーにある GameObject 名(callbackGameObject)の結果用メソッド(resultCallbackMethod)に文字列で返ってくる。またキャンセルボタンを押した時と、Android のダイアログの場合、範囲外をクリックするとダイアログが消えるが、その場合は何も返って来ない
(※) サンプルでは「Assets/FantomLib/Module/VolumeSliderDialogController.cs」内の「ReceiveVolume()」を参照。

 また、スライダーを音量設定などに使うとき、プレビュー再生などをリアルタイムで聴きたいときのために、もう1つ値変化のコールバックメソッド(changeCallbackMethod)も設定できるようにしてある。これを使う場合は、キー(itemKeys)を設定することにより、スライダーの値が変化するたびに "key=値" がコールバックされる(キーを設定しなかった場合は値だけなので、複数スライダーの場合、どのスライダーか判別できないので注意)。
(※) サンプルでは「Assets/FantomLib/Module/VolumeSliderDialogController.cs」内の「PreviewVolume()」を参照。

 一応簡単に、戻り値のスライダー値を取得するコードを書いておくと、 C# では、

string[] arr = result.Split('\n');       //result を結果の文字列とする
Dictionary<string, float> dic = new Dictionary<string, float>(); //キーと値の配列などでも良い
for (int i = 0; i < arr.Length; i++)
{
string[] param = arr[i].Split('='); //※キーがある前提の例
dic[param[0]] = float.Parse(param[1]);
}

//※ System.Linq を使うなら以下でも同じ
var dic = result.Split('\n').Select(e => e.Split(new char[]{'='}, 2)).ToDictionary(a => a[0], a => float.Parse(a[1]));

でも十分だろう。基本的に Android → Unity でのやりとりは一つづきの文字列なので、適宜加工して使うことになる(整数しか使わないなら、値は int 型で int.Parse() でも良い)。

 なお「マスター/音楽/ボイス/効果音」などの音量設定は使い回しし易いと考えたので、「Assets/FantomLib/Prefabs/System/」に「VolumeSliderDialogController.prefab」としてプレファブ化もしてある。これをヒエラルキーに置いてインスペクタで AudioSource を変更すれば簡単にプレビュー再生できると思う。Audio Mixer には「Assets/FantomLib/Sounds/」の「GameMixer」を設定してあるが、Exposed Parameters を合わせれば、入れ替えも可能だろう(ただし「マスター」のような全体音量を操作したい場合は、親子関係に注意)。簡単に言えば、このプレファブ(スクリプト)は音量をダイアログのスライダーで 0~100 (%) として設定し、それを AudioMixer のパラメタ名に対し -80~0db で変化させるものと考えて良い。他のアプリに組み込んで貰っても構わない。
(※) サンプルの素材はユニティちゃんボイスは UCL に準拠した形で、音楽(ループ曲)・効果音(ピンポンx2) は自作(Fantom) なので好きに使って貰って構わない。


 また、サンプルには設定などを簡単に保存できるように、PlayerPrefs を少し拡張して、真偽値、オブジェクト(クラス・構造体)、配列、リスト、辞書、キー&値ペア配列を保存できるクラスを「Assets/FantomLib/Scripts/System/XPlayerPrefs.cs」にまとめておいた。特にダイアログ専用というわけではないので、他のデータ保存など自由に使って貰っても構わない。

 あと、Android のダイアログの仕様という感じなのだが、ダイアログに収まりきらないほどオブジェクトを並べた場合、メッセージ文字列(タイトルの下に表示される文字列)が非表示となることに注意(タイトルと決定ボタンのみは上下に固定され、並べたオブジェクトはスクロールされる)。どうしてもメッセージ文字列を表示したい場合は、ダイアログの大きさに収まる数で配置して、いくつかのダイアログに分けた方が良いだろう(そちらの方がスクロールで見えない部分もなく、項目を探しやすいというメリットもある)。

 また、テキスト色に関しては、プラグインは Java で作ってあるため int 型の ARGB 形式になっているが、少し不便に感じたので、Unity の Color 形式のオーバーロードも作っておいた。あと少し特殊な仕様として色のパラメタ(ここでは itemsTextColor)に int値で 0 (= Color.clear)を与えた場合「指定なし」となるようにしてある(本来なら 0 は無色透明になるが、テキスト色には必要ないため)。ダイアログのスタイルの引数(ここでは style)を当てることもやってみたが、上手く反映されないようなので、個別に設定するようにした次第だ。指定するのが面倒なときはとりあえず 0 にしておけば良い(通常は黒になると思う)。また、int 型の ARGB 形式と Unity の Color 形式の相互変換は「Assets/FantomLib/Scripts/Graphics/XColor.cs」にまとめておいたので、自由に使って貰っても構わない。

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

(参考)R.style.theme

 サンプルコードは「Assets/FantomLib/Module/VolumeSliderDialogController.cs」にまとまっているので、全体的に見て貰えば使い方は難しくないだろう。



 実際の Java コードは色々値をチェックしたり条件分岐したり、高速化のためにキャッシュしたり、StringBuilderを使ったりしているが、長くなるのでここでは簡略化したものを書いてあると考えて欲しい。Java を知っている人なら中身は非常に簡単なものばかりなので、AndroidStudio を使ったことあるなら AAR プラグインをビルドするのに挑戦してみるのも良いだろう。


※この記事のUnityアセットはプラグインとして配布されています。



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


スポンサーサイト

category: Unity

thread: ゲーム開発

janre: コンピュータ

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



トラックバック

トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/281-22cb9c5c
この記事にトラックバックする(FC2ブログユーザー)

プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop