UnityのUI Toolkitでキーボードの押下イベントをハンドリングする方法についてまとめました。
Unity 2022.3.13f1
KeyDownEventとKeyUpEvent
キーボードの押下・離上をハンドリングするには、以下のようにKeyDownEvent
とKeyUpEvent
を使います。
using System; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; public sealed class Example : EditorWindow { private void CreateGUI() { var container = new VisualElement(); container.name = "container"; container.Add(new Label("Press any key to see the event")); container.Add(new TextField()); container.style.flexGrow = 1.0f; // キー押下イベントのリスナを登録 container.RegisterCallback<KeyDownEvent>(evt => { var message = $"KeyDown: {evt.target}{Environment.NewLine}" + $" keyCode: {evt.keyCode}{Environment.NewLine}" + // 押下されたキーボードのキー $" modifiers: {evt.modifiers}{Environment.NewLine}" + // Shift, Controlキーなどが押下されていたらここに入ってくる $" character: {evt.character}"; Debug.Log(message); }, TrickleDown.TrickleDown); // TextFieldはイベントの伝播を止めるため、この例ではTrickleDownフェイズ時点でハンドリングしている // キー離上イベントのリスナを登録 container.RegisterCallback<KeyUpEvent>(evt => { var message = $"KeyUp: {evt.target}{Environment.NewLine}" + $" keyCode: {evt.keyCode}{Environment.NewLine}" + $" modifiers: {evt.modifiers}{Environment.NewLine}" + $" character: {evt.character}"; Debug.Log(message); }, TrickleDown.TrickleDown); rootVisualElement.Add(container); } [MenuItem("Example/Example")] public static void ShowWindow() { GetWindow<Example>(); } }
説明はコメントに書いた通りです。
Example > Exampleメニューからウィンドウを開いてテキストフィールドに文字を入力するとログが出力されることを確認できます。
なおUI Toolkitにおけるイベント伝播の仕組みについて(RegisterCallback
やTrickeDown
などについて)は以下の記事にまとめていますので、必要に応じて参照してください。
characterプロパティについて
KeyDownEvent
でキーボードのどの物理キーが押下されたかを取得するには、前節の通りKeyDownEvent.keyCode
やKeyDownEvent.modifiers
を参照します。
これに対して、文字キーが押下されたときにはKeyDownEvent.character
に値が入ったイベントが追加で発行されます。
character
はkeyCode
とは異なり、物理キーではなく入力された文字を表します。
例えば大文字や小文字を判別したい場合にはこちらのイベントおよびcharacter
プロパティを使用します。
フォーカスについて
KeyDownEvent
やKeyUpEvent
はフォーカスされているVisual Elementをターゲットとして発行されます。
すなわち、Visual Elementがfocusableであり、かつフォーカスされていないといけません。
ここまでの例では、focusable
なVisuale ElementはTextField
のみなので、TextField
上でしかログが出力されないことを確認できるはずです。
もしテキストフィールド以外でイベントをハンドリングしたい場合には、以下のようにVisual Elementをfocusable
にします(containerをfocusableにしています)。
using System; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; public sealed class Example : EditorWindow { private void CreateGUI() { var container = new VisualElement(); container.name = "container"; container.Add(new Label("Press any key to see the event")); container.Add(new TextField()); container.style.flexGrow = 1.0f; // containerもフォーカスをできるように container.focusable = true; container.RegisterCallback<KeyDownEvent>(evt => { var message = $"KeyDown: {evt.target}{Environment.NewLine}" + $" keyCode: {evt.keyCode}{Environment.NewLine}" + $" modifiers: {evt.modifiers}{Environment.NewLine}" + $" character: {evt.character}"; Debug.Log(message); }, TrickleDown.TrickleDown); container.RegisterCallback<KeyUpEvent>(evt => { var message = $"KeyUp: {evt.target}{Environment.NewLine}" + $" keyCode: {evt.keyCode}{Environment.NewLine}" + $" modifiers: {evt.modifiers}{Environment.NewLine}" + $" character: {evt.character}"; Debug.Log(message); }, TrickleDown.TrickleDown); rootVisualElement.Add(container); } [MenuItem("Example/Example")] public static void ShowWindow() { GetWindow<Example>(); } }
Example > Exampleメニューからウィンドウを開くと、今度はどこでキーボードを入力してもイベントがハンドリングできていることを確認できます。