Version: 2022.1
言語: 日本語
ランタイム UI のパフォーマンスに関する考慮点
テキストを扱う

UI Toolkit を使用した入力およびイベントシステムに関する FAQ

このページでは、UI Toolkit でイベントシステムや入力システムを使用する際によくある質問を掲載しています。

  1. ランタイムパネルからマウスがビジュアル要素上にあるかを知るにはどうすればよいですか
  2. 基本的な UI アクションを再マップするにはどうすればよいですか
  3. 方向ナビゲーションを使用しているときに、次にフォーカスされる要素を変更するにはどうすればよいですか
  4. 方向ナビゲーションの WASD 入力や送信アクションのスペースバーをなくすことは可能ですか
  5. マウスでどこもクリックせずにキーボード入力を始めるにはどうしたらいいですか

ランタイムパネルからマウスがビジュアル要素上にあるかを知るにはどうすればよいですか

これには 2 つの方法があります。

最初の方法

  1. com.unity.uGUI パッケージからゲームオブジェクトベースの UI コンテンツを作成するのと同じ方法で、シーンに Event System コンポーネントを加えます。

  2. EventSystem.current.IsPointerOverGameObjectメソッドを使用し、ポインタがuGUIまたはUI ToolkitのUIコンテンツ上にある場合にtrueを返します。

  3. EventSystem.current.RaycastAll メソッドを使用して、マウスの下にあるビジュアル要素を確認します。

  4. 交差した UI Toolkit パネルは、ゲームオブジェクトを通して Event System の環境に表示されます。

    • ゲームオブジェクトの名前は、対応する PanelSettings と一致します。
    • ゲームオブジェクトの親は、現在の Event System コンポーネントを保持しているゲームオブジェクトです。
    • ゲームオブジェクトには 2 つのコンポーネント、PanelRaycasterPanelEventHandler があります。どちらのコンポーネントも、ターゲットとする IPanel を返す panel プロパティを持っています。

ポインターの下にパネルを見つけたら、panel.Pick メソッドを呼び出し、ポインターの位置にあるビジュアル要素を探します。

RuntimePanelUtils.ScreenToPanel メソッドを使用して、ポインターのスクリーン座標をパネル座標に変換する必要があります。

uGUI のスクリーン座標系は左下の原点を使用しますが、UI Toolkit のスクリーン座標は左上から表現されます。2 つのシステム間で変換するには、yTopLeft = Screen.height - yBottomLeft で Y 座標をミラーリングするか、その逆を行う必要があります。

第 2 の方法

  1. 使用される個別の PanelSettings ごとに、1 つの UIDocument からUIDocument.rootVisualElementプロパティを使用して、ポインターの下にあるすべてのランタイムパネルのリストを取得します。
  2. 手動でパネルを深さの順に見ていき、ビジュアル要素を返すパネルを見つけるまで、それぞれのパネルに対して panel.Pick を連続して呼び出します。

基本的な UI アクションを再マップするにはどうすればよいですか

基本的な UI アクションを再マップするには、以下を行います。

  1. com.unity.uGUI パッケージからゲームオブジェクトベースの UI コンテンツを作成するのと同じ方法で、シーンに Event System コンポーネントを加えます。
  2. Inspector ウィンドウで、Stand alone Input Module または Input System UI Input Module フィールドを設定して、どの入力を各アクションにマップするかを制御します。

ノート: Tab 入力と Shift+Tab 入力にマップされたアクションは、イベントシステムの入力モジュールを通して公開されていないため、再マップすることはできません。

方向ナビゲーションを使用しているときに、次にフォーカスされる要素を変更するにはどうすればよいですか

方向ナビゲーションは、デフォルトのターゲット以外にも設定できます。

次のコード例では、要素 A が上下左右に移動するときに、それぞれ要素 U、D、L、R に移動することが可能です。

A.RegisterCallback <NavigationMoveEvent>(e =>
{
    switch(e.direction)
    {
        case NavigationMoveEvent.Direction.Up: U.Focus(); break;
        case NavigationMoveEvent.Direction.Down: D.Focus(); break;
        case NavigationMoveEvent.Direction.Left: L.Focus(); break;
        case NavigationMoveEvent.Direction.Right: R.Focus(); break;
    }
    e.PreventDefault();
});

方向ナビゲーションの WASD 入力や送信アクションのスペースバーをなくすことは可能ですか

はい、可能です。EventSystem の StandaloneInputModule またはInputSystemUIInputModule Inspector フィールドを使用して、どの入力が各アクションにマップされるかを制御できます。ただし、これらのアクションは uGUI 入力と共有されるので、uGUI コントロールも変更されます。

uGUI コントロールに影響を与えずに UI Toolkit の入力を再マップするには、UI Toolkit のランタイムイベント処理を無効にし、すべてのイベントを手動でパネルに送信します。

マウスでどこもクリックせずにキーボード入力を始めるにはどうしたらいいですか

ゲームシーンを初めてロードするときなど、フォーカスが当たっている要素やパネルが存在しないことがあります。この場合、キーボードナビゲーションは予測可能な最初の要素から始まりません。これは、完全にマウスなしでプレイするゲームでは問題になることがあります。

最初から予測可能なナビゲーション動作ができるようにするには C# スクリプトを加えて、スクリプトを、最初のフォーカスを得るように選択した要素を処理する UIDocument と同じゲームオブジェクトにアタッチします。

スクリプトの名前を FirstFocus とし、最初にフォーカスされる要素の名前をfirst-focused とします。スクリプトの Start() メソッドに、その要素をフォーカスするコードを以下のように追加します。

public class FirstFocus : MonoBehaviour
{
    void Start()
    {
        FocusFirstElement();
    }

    public void FocusFirstElement()
    {
        GetComponent<UIDocument>().rootVisualElement.
            Q<VisualElement>("first-focused").Focus();
    }
}

ノート: UIDocument のゲームオブジェクトを無効にすると、その下にある階層はすべて最初から作り直されます。したがって、ゲームオブジェクトを再度有効にした後、カスタムの FocusFirstElement() メソッドを再度実行する必要があります。

その他の参考資料

ランタイム UI のパフォーマンスに関する考慮点
テキストを扱う