【Unity2D】ボタンの押し状態カウントとリセットの実装

Unity2D

Unity2D ARPG

ゲームにおけるボタンのカウント状態の重要性

次回のメッセージ送りを作る前に少し注意点を言っておくと、メッセージを開くときにAを押すわけですよね。

その間Aが押されているという状況になっています。

ここでAが押されたらメッセージを送るという風にすると、開いた瞬間にメッセージ送りが発動してしまうので
なんとかして制御をしてやらなければいけません。

プチコンやJavaScriptで作ってた時なんかはボタンカウントを設けて、
カウントが1の時でなければ反応しないように作っていました。

Unityではおそらくそういった仕組みが用意されてるかもしれませんが、
調べてる時間もないので既存の方法でチャレンジしてみましょう。

まずはコントローラーマネージャー側でボタンカウントをするようにしてみます。

    // キーカウント
    protected static int[] _pushedKeyCount = {
        1, // Aキー
        0, // Sキー
        0, // Dキー
        0, // Fキー
        0, // Gキー
        0, // Zキー
        0, // Xキー
        0, // Cキー
        0, // Vキー
        0, // Bキー
    };

    // キーカウント配列取得
    protected int getPushedKeyCount(int i)
    {
        return Controller_Manager._pushedKeyCount[i];
    }
    // キーカウント配列インクリメント
    protected void pushedKeyCountInc(int i)
    {
        if (i > -1) {
            Controller_Manager._pushedKeyCount[i]++;
        }
    }
    // キーカウント配列リセット
    protected void pushedKeyCountReset(int i)
    {
        if (i <= -1)
        {
            // マイナスの値であれば全キーカウントリセット
            for (int j = 0; j < Controller_Manager._pushedKeyCount.Length; j++)
            {
                Controller_Manager._pushedKeyCount[j] = 0;
            }
        }
        else
        {
            // -1以下でなければ指定配列のみリセット
            Controller_Manager._pushedKeyCount[i] = 0;
        }
    }

いまいちゲッターとセッターの扱い方がわかってないので、体験版を作り終わったらしっかりと勉強して
もうちょっと効率の良い安全性の高いコードを目指していきたいと思います。

とりあえず今は動いてくれればいいので、これでいきましょう。

軽く説明すると、int型の配列を用意してそれぞれのキーのカウント変数を用意しました。

本当は名前付きの法がわかりやすいと思うのですがDictionaryとかを使うといろいろと厄介なので
簡単にやるためにint配列を使っています。

本番環境はどうなるかはまだ未定ですね。

用意した関数は

  • 指定のキーカウントの現在値を取得
  • 指定キーのカウントを増やす
  • 指定キーのカウントをリセットまたは全キーカウントのリセット

を設けました。

あとは押されているキーに対してそれぞれの対応する配列にインクリメントするような仕組みを作りましょう。

現在押されているキーというリスト変数を作ったと思うので、あれを渡してカウントするようにします。

ついでにリセット用の関数も作ります。

    // キーカウント処理
    protected void selectPushedKeyCount(List<KeyCode> keyList) {
        for (int i = 0; i < keyList.Count; i++) {
            switch(keyList[i]) {
                case KeyCode.A:
                    pushedKeyCountInc(0);
                    break;
                case KeyCode.S:
                    pushedKeyCountInc(1);
                    break;
                case KeyCode.D:
                    pushedKeyCountInc(2);
                    break;
                case KeyCode.F:
                    pushedKeyCountInc(3);
                    break;
                case KeyCode.G:
                    pushedKeyCountInc(4);
                    break;
                case KeyCode.Z:
                    pushedKeyCountInc(5);
                    break;
                case KeyCode.X:
                    pushedKeyCountInc(6);
                    break;
                case KeyCode.C:
                    pushedKeyCountInc(7);
                    break;
                case KeyCode.V:
                    pushedKeyCountInc(8);
                    break;
                case KeyCode.B:
                    pushedKeyCountInc(9);
                    break;
                default:
                    break;
            }
        }
    }

    // キーカウントリセット処理
    protected void selectPushedKeyCountReset(KeyCode keyCode)
    {
        switch (keyCode)
        {
            case KeyCode.A:
                pushedKeyCountReset(0);
                break;
            case KeyCode.S:
                pushedKeyCountReset(1);
                break;
            case KeyCode.D:
                pushedKeyCountReset(2);
                break;
            case KeyCode.F:
                pushedKeyCountReset(3);
                break;
            case KeyCode.G:
                pushedKeyCountReset(4);
                break;
            case KeyCode.Z:
                pushedKeyCountReset(5);
                break;
            case KeyCode.X:
                pushedKeyCountReset(6);
                break;
            case KeyCode.C:
                pushedKeyCountReset(7);
                break;
            case KeyCode.V:
                pushedKeyCountReset(8);
                break;
            case KeyCode.B:
                pushedKeyCountReset(9);
                break;
            default:
                break;
        }
    }

なんか非効率な書き方ですが、きれいな書き方がわからないので愚直にカウントとリセットを書きました。

説明しておくと、カウントは押されているキー配列に対してですが、
リセットの場合は話されたときに何のキーかわかるようにしているのでその離されたキーに対して
カウントリセットをかけるようにしています。

これでカウント参照・カウント加算・カウントリセットと準備が整いました。

まずはリセットの仕組みを与えてみましょう。

Controller_Player側で離された時の処理に先ほどの関数を追記します。

    // キーのリスト入れ替え関数
    private void KeyAddRemove(KeyCode keycode)
    {
        if (Input.GetKey(keycode))
        {
            // Linqの機能:リストに指定物が中身になければリストに加える
            if (!(PushedArrowKeyList.Contains(keycode)))
            {
                // あれば削除
                PushedKeyList.Add(keycode);
                // 方向キーのみ
                PushedArrowKeyList.Add(keycode);
            }
        }
        else
        {
            // Linqの機能:リストに指定物が中身にあればリストにから外す
            if (PushedArrowKeyList.Contains(keycode))
            {
                // あれば削除
                PushedKeyList.Remove(keycode);
                // 方向キーのみ
                PushedArrowKeyList.Remove(keycode);
                // キーカウントリセット
                selectPushedKeyCountReset(keycode); // ※※追記はここだけ※※
            }
        }
    }

そしてカウント関数も毎フレーム呼び出しておきましょう。

    protected override void Update()
    {
        // キー入力監視
        KeyCheck();
        // キーカウント
        selectPushedKeyCount(PushedKeyList);

        Debug.Log("Aキー[" + getPushedKeyCount(0) + "]");
        Debug.Log("Sキー[" + getPushedKeyCount(1) + "]");
        Debug.Log("Cキー[" + getPushedKeyCount(2) + "]");
    }

ここまでできたらカウントされているか確認します。

試しにAとSとDの数値を表示してみましょう。

Unity2D キーカウント

しっかりカウントとリセットができていますね!

これでメッセージ送りとかボタン制御が必要とする準備ができました。

ボタンカウントの最大値を決めておく

ボタンカウントはint配列で作ってますね。

マイナスもいけてしまいます。

本来であればuintというマイナスがないintのほうが安全なのですが、一旦このままいきましょう。

あとはint型の最大値、つまり「2,147,483,647」を超えてしまうとオーバーフローして「-2,147,483,648」となってしまいます。

正直ボタンカウントにこんな桁数いらないですよね。

ならshortとあbyte型にしろよって思うのですが、最近のPCはint型のほうが高速に処理できるらしい(真偽は不明)
と、調べていたらよく書いている人が多いので習ってint型にしています。

ですがカウントは正直0~255の256まであればいいんじゃないでしょうか。

ということで最後にカウントの制御を付け加えましょう。

    // キーカウント配列インクリメント
    protected void pushedKeyCountInc(int i)
    {
        if (i > -1)
        {
            if (Controller_Manager._pushedKeyCount[i] < 256)
            {
                // カウントは255まで
                Controller_Manager._pushedKeyCount[i]++;
            }
        }
    }

256未満ならインクリメントするといった感じですね。

これでオーバーフロー対策はできました。

次回はメッセージ送りと選択肢を実装してみましょう。

それでは!