はじめに
uGUIで最も使用頻度が高いと思われるButtonの基本的な使い方を紹介します
Buttonの作り方
まずはButtonの作り方からです。
メインメニューから GameObject > UI > Button
を選択します。
Buttonを選ぶと、Hierarchyビューに、Canvas / Button / Text / EventSystem
の4つのGameObjectが追加されます。
以下、簡単な説明です。
- Canvas: UIを乗せる領域。これがないとUIは作れない
- Button: ボタン。ここにボタンの挙動を設定する
- Text: ボタンの上に乗るテキスト
- EventSystem: UIイベントスクリプト管理。イベントを拡張したい場合はここに手を入れる
今回は、Buttonのクリック判定ができればいいので、EventSystemはそのまま使います。
ボタンの見た目の挙動を制御する
Hierarchyビューから Button
を選択します。するとInspectorビューにボタンの情報が表示されます。
パラメータが多くて混乱しそうですが、まずは Button (Script)
に注目します。ここでボタンの見た目を変更できます。
ここにある4つのColorパラメータに注目します。
- Normal Color: 初期の色
- Highlighted Color: マウスが上に乗った時の色
- Pressed Color: ボタンを押した時の色
- Disabled Color: ボタン無効化時の色
このパラメータを以下のように変更します。
- Normal Color: 白(そのまま)
- Highlighted Color: 赤
- Pressed Color: 青
- Disabled Color: 灰色(そのまま)
実行してみると、ボタンの上にマウスが乗ると「赤」になり、クリックすると「青」、その後は「赤」になりました。
- 初期状態→白
- ボタンの上にマウスが乗る→赤
- クリックする→青
- クリックを解除→赤
クリック解除時に赤になるのは、そのボタンにフォーカスがあるからです。画面内のどこかをクリックすると、フォーカスが外れて、白に戻ります。これは ナビゲーションモード
と呼ばれ、キーボードでの操作に対応するためのものとなります。この機能が不要な場合は Navigation
を None
に変更すること無効化できます。
丸ボタンにする
Buttonの Image (Script)
から Source Image
を選択して、Knob
スプライトを選択します。
すると四角いボタンが楕円形になります。
これを丸く変形させます。
Hierarchyビューの Button
オブジェクトをダブルクリックしてズームし、Sceneビューの上にあるツールバーから四角形のアイコンを選びます。
このアイコンを選ぶと、オブジェクトの変形モードとなり、端にある青い丸をドラッグするとオブジェクトを変形できます。
変形させて丸くしてみました。
クリックしたときの処理を実装する
ボタンをクリックしたときの処理を実装します。
メインメニューから Assets > Create > C# Script
を選択して、スクリプトを追加します。
そうしたらスクリプトを開いて以下のように記述します。
using UnityEngine;
using System.Collections;
public class MyButton : MonoBehaviour {
/// ボタンをクリックした時の処理
public void OnClick() {
Debug.Log("Button click!");
}
}
ボタンをクリックすると、"Button click!"というログを出力するようにしました。
スクリプトが書けたら保存して、Unityエディタに戻り、MyButton
スクリプトを、Button
オブジェクトにドラッグ&ドロップします。
次にHierarchyビューからButtonオブジェクト
を選択して、Inspectorビューの Button (Script)
コンポーネントから OnClick() の枠にある+ボタン
をクリックします。
すると項目が追加されるので、○をクリックしてオブジェクト選択ダイアログを表示します。
そこからButtonオブジェクト
を選択します。
次にとなりにある項目の No Function
をクリックすると、どの関数を呼び出すのかを選択するリストが表示されるので、MyButton > OnClick ()
を選びます。
実行してみます。ボタンをクリックすると、"Button click!"というログが出力されるはずです。
クリック処理を行うまでの流れの整理
ここまでの流れを整理すると以下のようになります。
OnClickには、「誰(主体者)」が「何をする(動作)」の設定をします。今回であればButtonオブジェクト
が主体者で、それが持つMyButtonスクリプトのOnClick()
という動作を呼び出す、という設定をしていることとなります。
Buttonの表示・非表示を切り替える
Buttonの表示・非表示を切り替えるには GameObject.SetActive()
を使用します。例えば、MyButton
スクリプトを以下のように修正します。
using UnityEngine;
using System.Collections;
public class MyButton : MonoBehaviour {
public void OnClick() {
Debug.Log("Button click!");
// 非表示にする
gameObject.SetActive(false);
}
}
実行してボタンをクリックすると、ボタンが非表示になります。ただ、この方法には問題があります。SetActive(false)
をすると、そのオブジェクトは GameObject.Find
で取得しようとしても検索対象外となってしまい、非表示したボタンを再表示することができなくなります。
そこで親のCanvasオブジェクトから、子の階層をたどってButtonオブジェクトを取得する方法を使います。
メインメニューから Assets > Create > C# Script
でスクリプトを追加し、スクリプトの名前は MyCanvas
とします。
スクリプトは以下のように記述します。
using UnityEngine;
using System.Collections;
using UnityEngine.UI; // ←※ここを追加する
public class MyCanvas : MonoBehaviour {
static Canvas _canvas;
void Start () {
// Canvasコンポーネントを保持
_canvas = GetComponent<Canvas>();
}
/// 表示・非表示を設定する
public static void SetActive(string name, bool b) {
foreach(Transform child in _canvas.transform) {
// 子の要素をたどる
if(child.name == name) {
// 指定した名前と一致
// 表示フラグを設定
child.gameObject.SetActive(b);
// おしまい
return;
}
}
// 指定したオブジェクト名が見つからなかった
Debug.LogWarning("Not found objname:"+name);
}
}
このスクリプトは生成時(Start)にCanvasコンポーネント
を保持します。そして、SetActive関数を呼び出すと、Canvasの子要素から一致するオブジェクト名を探し表示・非表示の設定を行います。
そしてこのスクリプトを、Canvasオブジェクト
にドラッグ&ドロップしてアタッチします。
これでボタンの表示・非表示を、外部から切り替えられるようになります。
確認用に、もう1つボタンを配置して、交互に表示を切り替えるようにしています。
-
メインメニューから
GameObject > UI > Button
でボタンを作成します -
メインメニューから
Assets > Create > C# Script
でスクリプトを作成します
MyButton2スクリプト
を開いて以下のように編集します。
using UnityEngine;
using System.Collections;
public class MyButton2 : MonoBehaviour {
public void OnClick() {
Debug.Log("Button2 click!");
// 非表示にする
gameObject.SetActive(false);
// Buttonを表示する
MyCanvas.SetActive("Button", true);
}
}
これで自分自身を非表示にした後、別のButtonを表示できるようになります。
ついでにMyButton
スクリプトも修正しておきます。
using UnityEngine;
using System.Collections;
public class MyButton : MonoBehaviour {
public void OnClick() {
Debug.Log("Button click!");
// 非表示にする
gameObject.SetActive(false);
// Button2を表示する(※ここを追加)
MyCanvas.SetActive("Button2", true);
}
}
Button2のOnClickを設定します。HierarchyビューからButton2オブジェクト
を選び、Inspectorビューから、Button (Script)
コンポーネントの設定をします。
手順は、
-
On Click()
の+ボタン
をクリック -
Button2オブジェクト
を設定 -
MyButton2 > OnClick
を登録
となります。
実行して動作を確認します。クリックしたボタンが消え、別のボタンをクリックすると別のボタンが再表示されるようになります。
ボタンのテキストを変更する
ボタンの子にTextオブジェクト
がある、という前提であれば、 ボタンオブジェクトの子の要素を調べる ことで、Textオブジェクトを取得することができます。
このような階層になっていることが前提とします。この場合、前に説明した MyCanvasスクリプト
に以下の関数を追加します。
/// テキストを変更する
public static void SetText(string name, string text) {
foreach(Transform child in _canvas.transform) {
// 子の要素をたどる
if(child.name == name) {
// 名前が一致
foreach(Transform child2 in child.transform) {
// 孫要素をたどる
if(child2.name == "Text") {
// テキストを見つけた
Text t = child2.GetComponent<Text>();
// テキスト変更
t.text = text;
// おしまい
return;
}
}
}
}
// 指定したオブジェクト名が見つからなかった
Debug.LogWarning("Not found objname:"+name);
}
該当するButtonオブジェクト
を探し、さらにその子要素Text
を探し、テキスト文字列を設定します。
使い方は、例えばこんな感じです。
MyCanvas.SetText("Button2", "New Button");
注意点
「テキストを変更」するスクリプトはGetComponent
を使用しているため若干重たい処理となります。なので、頻繁に更新する場合は、一番最初にTextオブジェクト
を直接取得し、それ以降はTextオブジェクトに直接設定する方が処理が軽くなります。
/// 指定のオブジェクトのTextを探す
public static Text FindText(string name) {
foreach(Transform child in _canvas.transform) {
// 子の要素をたどる
if(child.name == name) {
// 指定した名前と一致
foreach(Transform child2 in child.transform) {
// 孫要素をたどる
if(child2.name == "Text") {
return child2.GetComponent<Text>();
}
}
}
}
// 指定したオブジェクト名が見つからなかった
Debug.LogWarning("Not found objname:"+name);
return null;
}
使う側のサンプルです。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class GameMgr : MonoBehaviour {
Text text;
void Start() {
// 開始時に取得
text = MyCanvas.FindText("Button2");
}
void Update() {
// 毎フレームテキストを設定
text.text = "" + Time.deltaTime;
}
ボタンを無効化する
ボタンを無効化するには、Buttonコンポーネント
のinteractable
フラグを使用します。
例えば、MyCanvas
クラスに以下の関数を実装します。
/// ボタンの有効・無効を設定する
public static void SetInteractive(string name, bool b) {
foreach(Transform child in _canvas.transform) {
// 子の要素をたどる
if(child.name == name) {
// 指定した名前と一致
// Buttonコンポーネントを取得する
Button btn = child.GetComponent<Button>();
// 有効・無効フラグを設定
btn.interactable = b;
// おしまい
return;
}
}
// 指定したオブジェクト名が見つからなかった
Debug.LogWarning("Not found objname:"+name);
}
例えばこんな関数を作っておけば、他のクラスから有効・無効が設定できます。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class MyButton : MonoBehaviour {
public void OnClick() {
Debug.Log("Button click!");
// 自分自身を無効化する
MyCanvas.SetInteractive("Button", false);
}
}
こんな感じでグレーになって無効化しました(左の丸ボタン)。
この状態になると、クリックしても何も反応しなくなります。