Roba Memo - 素人のUnity覚書と奮闘記

素人のUnity覚書と奮闘記

スクリプトごと使いまわしできる 数字ボタン その1:ベースボタンの作り方

こんな感じのボタンを作る方法をメモ。
f:id:nico-taniku:20170618082200p:plain:w300
主な機能は、
・上をクリックしたら1ずつ減算し、下をクリックしたら1ずつ加算する。
・長押しすることで、数字を送りつづける。
・Enterボタンで判定。

ボタンをPrefabにして、それを使いまわしすればいいんだけど、毎回、桁数や答えが違うから、その都度スクリプトを書いてアタッチするのは、正直めんどくさい。
ということで、prefabのインスペクターで、設定(変数値)を変えるだけで使えるボタンを作って見た。
長くなるので、その1ではスクリプトを含めたベースボタンの作り方をメモ。

1:ボタンを作る

配置はこんな感じ。
mask,Text0,Text1,Text2の名前はスクリプトから参照するので変更不可。
f:id:nico-taniku:20170616220252p:plain

NumberButtonは、ButtonじゃなくてImageで背景画像を設定しておく。
f:id:nico-taniku:20170616220116j:plain

Text0〜Text2は、左から順に並べる。

9 ← Text0の数字 = 保管する数字
0 ← Text1の数字 = 現在の数字
1 ← Text2の数字

画像より少しはみ出るように並べて、3つのテキストにマスクをかける。
↓Text0の位置になる。
f:id:nico-taniku:20170616220840p:plain:w150

↓マスクの領域。
f:id:nico-taniku:20170616221117p:plain:w150

クリックポイントは、指でタップするので、少し大きめに取っておく。
↓減算ボタン
f:id:nico-taniku:20170616221434p:plain:w150

↓加算ボタン
f:id:nico-taniku:20170616221458p:plain:w150

このボタンを作成し、とりあえずPrefabにしておく。

2:Global(シングルトンクラス)に、入力された数字を保管するための変数を作る

入力された数字を保持しておけば、再表示のときに再現できるので、そのための変数を作成する。
同じシーン内で呼び出すだけなので、シングルトンクラスじゃなくてもステージ上で保持できればOK。
中身はスクリプトで追加していくので、空のままで初期化だけしておく。

[HideInInspector]
public Dictionary<string,int[]> NumberButtonDictionary = new Dictionary<string,int[]> { };

string(キー) = 識別用
int[] (値) = 各ボタンの一番上のテキストの数字 長さは桁数に合わせる。

3:ボタンにアタッチするクラスを作成する

スクリプトの説明は後ほど。

完成スクリプト

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class NumberButton : MonoBehaviour
{

    [SerializeField][Header ("答え")]string answer;
    [SerializeField][Header ("ボタン識別番号 0〜")]int btnNumber;
    [SerializeField][Header ("長押し判定するまでの秒数")]float longPress = 0.5f;
    [SerializeField][Header ("文字を送る速度")]float speed = 0.2f;
    [SerializeField][Header ("Dictionary Key")]string keyName;

    //3つのテキスト
    Text[] texts;
    //長押しかどうか
    bool flag = false;
    //Updateの待機時間カウント用
    float passtime;
    //加算ボタンを押したかどうか
    bool next = false;

    void Awake ()
    {
        //テキストの取得
        texts = new Text[3];
        for (int i = 0; i < texts.Length; i++) {
            texts [i] = transform.Find ("mask/Text" + i).GetComponent<Text> ();
        }
        //初期化
        passtime = longPress;
    }

    void Start ()
    {
        //Dictionaryに追加
        if (!Global.instance.NumberButtonDictionary.ContainsKey (keyName)) {
            int[] array = new int[answer.Length];
            for (int i = 0; i < array.Length; i++) {
                array [i] = 9;
            }
            Global.instance.NumberButtonDictionary.Add (keyName, array);
        }

        //テキストの初期表示
        int first = Global.instance.NumberButtonDictionary [keyName] [btnNumber];
        for (int i = 0; i < texts.Length; i++) {
            texts [i].text = first.ToString ();
            first++;
            if (first == 10) {
                first = 0;
            }
        }
    }

    void Update ()
    {
        if (flag) {
            passtime -= Time.deltaTime;
            if (passtime <= 0.0) {
                passtime = speed;
                SetNumber ();
            }
        }
    }

    public void OnDown (bool nextFlag)
    {
        flag = true;
        next = nextFlag;
        SetNumber ();
        //効果音
        AudioManager.instance.PlaySE (0);
    }

    public void OnUp ()
    {
        flag = false;
        passtime = longPress;
        next = false;
    }

    void SetNumber ()
    {
        if (next) {
            int value = int.Parse (texts [0].text);
            for (int i = 0; i < texts.Length; i++) {
                value++;
                if (value == 10) {
                    value = 0;
                }
                texts [i].text = value.ToString ();
                if (i == 0) {
                    Global.instance.NumberButtonDictionary [keyName] [btnNumber] = value;
                }
            }
        } else {
            int value = int.Parse (texts [2].text);
            for (int i = texts.Length - 1; i >= 0; i--) {
                value--;
                if (value < 0) {
                    value = 9;
                }
                texts [i].text = value.ToString ();
                if (i == 0) {
                    Global.instance.NumberButtonDictionary [keyName] [btnNumber] = value;
                }
            }
        }
    }

    public bool OnEnter ()
    {
        bool ans = false;
        string str = "";
        //効果音
        AudioManager.instance.PlaySE (0);

        foreach (int value in Global.instance.NumberButtonDictionary [keyName]) {
            int num = value + 1;
            if (num == 10) {
                num = 0;
            }
            str += num.ToString ();
        }
        if (answer == str) {
            ans = true;
        }
        return ans;
    }
}

4:ボタンにアタッチする

手順1のボタンに、手順3のクラスをアタッチする。
f:id:nico-taniku:20170617170543p:plain:w500
長押し判定する秒数と、文字を送る速度を設定する。
それぞれ、数値が大きいほうが遅くなる。1秒=1.0f
それ以外は、実際に使うときに設定する。

5:ボタンイベントを設定する

ボタンにOnDown()とOnUp()を追加する。
OnDown()に、加算するかどうかをチェックする引数があるので、加算する場合はチェックを入れる。

ボタン上部に配置した減算ボタン
f:id:nico-taniku:20170617171444p:plain:w300
下の加算ボタン
f:id:nico-taniku:20170617171541p:plain:w300

この状態で、一旦prefabを保存する。

続きは、その2で。