UnityのUGUIのボタンで、「起動して初回だけは複数回押さないと正常な反応をせず、いったん正常な反応に至った後は普通に1回押しただけで正常に動く」という症状にお悩みの方向けの記事です。
Unityのボタンについて、「何回押してもうんともすんとも言わない不具合」についてはググると解説記事がいくつも出てきます。
が、この記事では
- 起動して初回は複数回押さないと反応しない、もしくは予期せぬ動作をする(他のボタンに割り当てた動きなど)
- ひとたび正常な操作をしはじめたら、その後は1回押しただけで正常な動きをするようになる
という症状について記載します。
症状例
私が遭遇した本件の症状は、下記の通りです。
ボタンを多数配置していくつかのボタングループにまとめ、ボタンを押すことによってどのボタングループを表示する(SetActive(true))のか切り替えるアプリを作っていました。いくつかのメニュー画面をボタン押下によって遷移するイメージです。
初期画面:ボタンa押下
↓
メニューB:ボタンb押下(キャンセルボタン有り)
↓
メニューC:ボタンc押下(キャンセルボタン有り)
↓
メニューD:ボタンd押下(キャンセルボタン有り)
・・・
症状としては、
実行して初回はボタンaを5回押さないとメニューBが現れず、
メニューBが現れてもボタンbを押すと初期画面に戻ってしまい(キャンセルボタン押下と同じ動き)、
ボタンa→ボタンbという操作を5回連続でやらないとメニューCが現れず、、
という感じで、メニュー階層を深めに設計していたので最下層にたどり着くには何十回もボタンを一定の順番でクリックしなければならないという地獄に陥りました。
しかし、ひとたび下層のメニューにたどり着けば、その後は初期画面から当該層のメニューにたどり着くまでは正常な動作をするのです。
なお、エラーメッセージは一切出ません。
原因
この症状は、Update関数を含む同一のスクリプトファイルを複数のオブジェクトにアタッチした場合に発生します。
ありがちだろうと思われるのは、空のオブジェクトにアタッチした監督スクリプトのスクリプトファイルにボタンのOnClick関数を書き込んだ場合です。この場合、空のオブジェクトとボタンにUpdate関数を含んだ同一のスクリプトファイルをアタッチすることとなり、予期せぬ動きの原因になります。
厄介なのは、この不具合はエラーメッセージが出て停止する原因にはならないためにスクリプトのどこが悪さをしているのか極めて特定しづらいことです。
対策
対策としては、まずはUpdate関数を含む同一のスクリプトファイルを複数のオブジェクトにアタッチしていないかどうか確認しましょう。
もしそのようなスクリプトファイルがあったら、一つのUpdate関数を含むスクリプトファイルは一つのオブジェクトにしかアタッチしないようにスクリプトファイルを切り分けましょう。
別のスクリプトに分けると、関数や変数を呼び出すときに一々GetComponent<T>();で呼び出さなければならなくなり面倒この上ないですが、おそらく同一スクリプトファイルにある限りこの問題は解決できないのではないかと思います。