口内炎
唇が痺れるぐらい痛かった口内炎がやっと治ったと思ったら今度は奥歯が知覚過敏になった口内衛生には気を使っているつもりの皆さんこんにちは。日中の気温は暖かくなってきましたが水道水は未だに冷たいのでうがいをする時には注意が必要になります。歯医者行こうかな。
プレイ動画
先日出展したTOKYO INDIE GAMES SUMMITではあまり良い成果が出せず結構落ち込んでいたのですが、とはいえ一応記録には残しておこうと出展したバージョンのプレイ動画を作成しYoutubeにアップしています。遊ぶことはできませんが、この動画で現在制作中の「Under A Groove」というゲームがどんな感じのゲームなのか分かって頂けると思います。
動画でも分かるように「Under A Groove」はリズムゲームでワンボタンで操作可能なんですが、現状では「ボタンを押すだけ」の操作だけなので少し変化を加える意味で音ゲーによくあるロングノーツ(長押しノーツ)を取り入れることにしました。
ボタン長押し
「長押し」を判定するには一定時間ボタン等の入力が継続されている事の判別が必要ですが、ゲームの入力デバイスがマウス、キーボード、ゲームコントローラー、Joyスティック等多岐にわたる場合、それを自力で実装するのは少し面倒で「Input System」を利用する方法がもっとも簡単だと思います。
「Input System」はUnity公式が提供しているパッケージで複数の異なる入力デバイスを一括で管理することが出来るパッケージです。
Input Sysytemの概要や導入方法は下の記事で非常に詳しく解説されています。
今回の場合、複数の入力デバイスによる「長押し」を判定したい=どの入力デバイスでも同じ「長押しイベント」を発生させたい、となるのでInput Systemが提供する「Input Action」を用いて「長押し判定→長押しイベント発生」の機能を実装したいと思います。
「Input Action」のついてはこのブログでも紹介したことがあります。
Input Actionsアセットの設定
「Input Action」を使うには「どの入力がどのイベントを発生させるのか」を決めるための「Input Actionsアセット」を作成する必要があります。メニューのAssets > Create > Input Actionsの順に選択して「Input Actionsアセット」を作成します。
新規に作成した場合は長押しの設定を登録する前に左上のActions Maps右の+ボタンをクリックし、Action Map名を入力を行ってください。
既にプロジェクト内にInput Actionsアセットが存在する場合はプロジェクト内にコントールが作成されているのでそれをダブルクリックします。
このAction Mapに長押しのActionを追加します。Actions欄の右の+ボタンをクリックして適当な名前を入力し、長押し入力を検知したいデバイスを追加します。
今回はActions名を「LongPress」という名に設定し、+アイコンから入力デバイスを追加、4つのボタンと左マウスボタンで入力を検知する設定を行っています。
右のBindingProperties欄のInteractionにて「長押し=Hold」によるイベントの通知を設定します。ウィンドウ右のAction Properties > Interaction右の+アイコン > Holdを選択します。
必要に応じて画面の項目の値を設定します。デフォルトではInput Systemパッケージの設定内容が反映されているので条件に合わない場合はDefalutのチェックを外して入力します。
- Press Point:入力あり判定となる閾値。アナログボタンでは0.0f~1.0fの値が取得されるので適切な値を入力
- Hold Time:長押し判定されるまでの時間(秒)。この時間以上の入力があると「長押し」と判定されイベントが発火
イベント取得のスクリプト
上記の設定後、長押し操作を行うとInputActionより長押し発生のイベント(preformed)および入力解除(canceled)のイベントが発火するようになるので取得するためのコールバックを登録します。
using UnityEngine; using UnityEngine.InputSystem; public class GetHoldExample : MonoBehaviour { // 入力を受け取る対象のAction private GameInputs _gameInputs; private void Awake() { // Actionスクリプトのインスタンス生成 _gameInputs = new GameInputs(); // performedコールバックのみを受け取る // 長押し判定になったらこのコールバックが呼ばれる _gameInputs.performed += OnHold; _gameInputs.canceled += OnHoldCancel; // 入力を受け取るためには必ず有効化する必要がある _gameInputs.Enable(); } // 長押しされたときに呼ばれるメソッド private void OnHold(InputAction.CallbackContext context) { Debug.Log("長押しされた!"); } // 入力解除されたときに呼ばれるメソッド private void OnHoldCancel(InputAction.CallbackContext context) { Debug.Log("ボタンが離された!"); } }
上記のようにスクリプトの実装は簡単に行えます。入力解除(canceled)のイベントは長押し発生のイベント(preformed)の発生有無にかかわらず入力デバイスからの入力値がPress Point以下の値になった時に発火するので注意が必要です。
実際にゲームに適用させてみるとこんな感じですかね。Input System側の設定&実装より「長押しノーツ」の表示制御の方に時間が掛かりました。
Input Systemを使えば長押しのロジックを書く必要がなく、Input Actionのperformedコールバックを拾えば良いだけなのでかなり楽ですね。