新しいInput SystemのOn-Screen Controlsでタッチスクリーン上にジョイスティックやボタンを作る方法をまとめました。
Unity2020.1
Input System 1.0.0
はじめに
本記事ではUnity2020のリリースと同時にVerifiedとなった新しいInput SystemのOn-Screen Controlsの使い方についてまとめます。
On-Screen Controlsはタッチスクリーン上に仮想的なボタンやジョイスティックを作るための機能です。
なおInput Systemの基礎知識については以下の記事にまとめていますので、必要に応じて参照してください。
On-Screen Button
さてそれでは実際に仮想的なボタンを作ってみます。
ボタンを作るにはまずuGUIで適当にButtonを作ります。
次にこのGameObjectにOnScreenButtonコンポーネントをアタッチします。
Control Pathにはこの仮想的なボタンが押されたときに呼び出されたことにするデバイスのボタンを指定します。
今回はGamePadのSouthボタンが呼ばれたものとみなす設定にしました。
あとはこの入力を受け取るためのActionを作ります。
今回は以下のようにInputActionを持つMonoBehaviourを作りました(本当はちゃんとInput Actionアセットを作ったほうがいいです)。
using UnityEngine; using UnityEngine.InputSystem; public class OnScreenExample : MonoBehaviour { [SerializeField] private InputAction _fireAction; private void Start() { _fireAction.performed += _ => Debug.Log("Fire"); } private void OnEnable() { _fireAction.Enable(); } private void OnDisable() { _fireAction.Disable(); } private void OnDestroy() { _fireAction.Dispose(); } }
そしてこのコンポーネントのInspectorからActionにGamePadのSouthボタンのバインディングを追加します。
これで再生して仮想的なボタンを押すと、正常にログが出力できることが確認できます。
On-Screen Stick
次に仮想的なジョイスティックを作ります。
まずuGUIで適当なImageを作っておきます。
そしてこのGameObjectにOnScreenStickコンポーネントをアタッチします。
Control Pathは Left Stick[GamePad] に設定しておきます。
この時点で再生するとuGUIが仮想スティックのように動くことが確認できます。
あとはボタンと同様入力を受け取るためのActionを作ります。
まずスクリプトは以下のように書きます。
using UnityEngine; using UnityEngine.InputSystem; public class OnScreenExample : MonoBehaviour { [SerializeField] private InputAction _moveAction; private void Start() { _moveAction.performed += _ => { var value = _moveAction.ReadValue<Vector2>(); Debug.Log($"Move: ({value.x}, {value.y})"); }; } private void OnEnable() { _moveAction.Enable(); } private void OnDisable() { _moveAction.Disable(); } private void OnDestroy() { _moveAction.Dispose(); } }
Inspectorの設定は以下のようにします。
2DのVector型で設定しているのと、CompositeのModeをAnalogにしている点に注意してください。
この状態で実行してスティックを動かすと正常にログが出力されることを確認できます。
自前のOn-Screen Controlsを作成する
下記のようにOnScreenControlクラスを継承すると自前のOn-Screen Controlを作成することができます。
using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem.Layouts; using UnityEngine.InputSystem.OnScreen; [AddComponentMenu("Input/On-Screen Button")] public class OnScreenButtonCustom : OnScreenControl, IPointerDownHandler, IPointerUpHandler { public void OnPointerUp(PointerEventData data) { SendValueToControl(0.0f); } public void OnPointerDown(PointerEventData data) { SendValueToControl(1.0f); } [InputControl(layout = "Button")] [SerializeField] private string m_ControlPath; protected override string controlPathInternal { get => m_ControlPath; set => m_ControlPath = value; } }
難しいことはないので説明は割愛しますが、詳しく知りたい場合にはOnScreenButtonやOnScreenStickのコードを見るのが良いかと思います。