Unityでゲームを作っているときに、ボタンを長押しして、押している間に特定のプログラムを動かしたい場合がありますよね。
この記事ではボタンを長押し状態の判定をどのようにスクリプトに作り込むのかを解説したいと思います。
基本を解説した後に、落とし穴的な要素についても説明しているので、最後まで読んでください。
【Unity】ボタンの長押し判定と押している間の処理を作る方法 ~基本編~
「ボタンを押している間」というのは、どういう状態かというと、ボタンをダウンして、アップしていない状態ですね。というわけで、ボタンの長押し判定はダウンしてアップしていない状態を管理するスクリプトを書けばOKです。
ボタンを押している間に処理をするスクリプトを作る
答えを先に書くと、次のようなスクリプトになります。
public class ButtonHoldDown : MonoBehaviour { // ボタンを押したときtrue、離したときfalseになるフラグ private bool buttonDownFlag = false; private void Update() { if (buttonDownFlag) { // ボタンが押しっぱなしの状態の時にのみ「Hold」を表示する。 Debug.Log("Hold"); } } // ボタンを押したときの処理 public void OnButtonDown() { Debug.Log("Down"); buttonDownFlag = true; } // ボタンを離したときの処理 public void OnButtonUp() { Debug.Log("Up"); buttonDownFlag = false; } }
変数buttonDwonFlagでボタンの状態を保持しています。
OnButtonDownがボタンが押されたときに動くメソッドで、フラグをtrueにします。フラグがtrueの時は押しっぱなしの状態なので、その場合にのみUpdateメソッドでフレーム毎に動く処理を実装しましょう。そして、OnButtonUpメソッドでボタンを離すので、フラグをfalseにします。
これで、ボタンを押している間の処理を組むことができるようになりましたね。今回の例だと、ボタンを押しっぱなしにしているとHoldが出続けるような処理です。
ボタンが押されたら動くイベントを追加する
処理を組んだら、残りはボタンにイベントを登録するだけです。if文は不要です。
ボタンのインスペクターにある「コンポーネントを追加」をクリックします。そして「イベント」-「イベントトリガー」と選択すると、「Event Trigger」がインスペクターに追加されます。
追加されたEvent Triggerにある「新しいイベントを追加」ボタンを押して、PointerDownとPointerUpのイベントをそれぞれ追加します。
追加したイベントに、作成したスクリプトをアタッチしてやれば、準備OKです。
実行して動作確認しよう
再生ボタンを押して、実際にボタンを長押ししてみましょう。下図が結果となります。
ボタンを押して「Down」を表示して、その間「Hold」が実行されています。その後、ボタンを離すと「Up」を表示し、「Hold」が表示されなくなりました。
これで、ボタンを押している間に特定の処理を動かすプログラムが組めましたね。
ただ、これだけでは処理が不十分なケースがあります。次に説明します。
【Unity】ボタンの長押し判定と押している間の処理を作る方法 ~追加知識~
ゲームのコントローラーなどのボタンなら、ボタンを長押ししている状態は基本編で事足りますが、マウスやスマホのタップの場合は、それだけでは不十分なケースがあります。
それは、ボタンをダウンした後、ボタンの上以外でアップする場合や、ボタンをダウンしていないのに、アップするイベントが動く場合を考慮する必要があることです。
要は「ボタンダウンとボタンアップが同じボタン上で実行されないケース」です。
ちょっと言葉だけじゃわからないと思うので、図解します。
ボタンダウンとボタンアップが同じボタン上で実行されないケース
上図のDown→Upが、同一ボタン上でボタンアップとボタンダウンが行われる例です。赤丸の部分で操作されていると思ってください。
左のDown→Upの場合だと、Upの時の処理がDownしていないのに動いてしまいます。もしDownしていることを前提としたプログラムの場合、不具合が発生してしまいます。
また右のDown→Upの場合だと、DownしてUpしていないので、ずっとボタンを押しっぱなしの状態になってしまっています。そのためUpしたのに、処理が止まりません。
ではどうすればいいのか?次に対策を説明します。
※仕様として、このケースを認める場合は対策不要ですが、不具合が発生しないかは十分検討してください。
対策1:Up時にはDownしていることを判定する処理を入れる
左のDown→Upの動きについては、Upの処理にDownしているかの判定を入れれば大丈夫です。具体的には次のように修正すればいいでしょう。
// ボタンを離したときの処理 public void OnButtonUp() { if (buttonDownFlag) { Debug.Log("Up"); buttonDownFlag = false; } }
対策2:ボタンから離れるイベントPointerExitを加える
右のDown→Upの動きについては、ボタンからマウスが外れた時に発生するイベントであるPointerExitイベントを使いましょう。
そしてPointerExitイベントに次のようなOnButtonExitメソッドを登録してやれば、ボタンを押して、そのままボタンから外れた時には、押しっぱなしの状態を解除してくれます。
public void OnButtonExit() { if (buttonDownFlag) { Debug.Log("Exit"); buttonDownFlag = false; } }
実行した結果は次のようになります。ちゃんと、Down→Hold→Exitで止まってますね。
まとめ
Unityでボタンを長押し判定と押している間に特定のプログラムを動かす方法をまとめました。
追加情報編で記した内容はある程度デバッグやってたら気付ける内容ではありますが、これぐらいの内容はプログラムを作っているとき、もしくはそれ以前の設計の段階で思いつけるようになると、一つレベルが上がっていると言えますね。
こういう細かいところの気づきは経験がものを言うので、初心者は気付けなくてもいいですが、それなりに経験を積んだ人には気付いてほしいですね。