参考元:
新しくデバイスを追加する
Devices | Input System | 1.0.2
PS4のコントローラーを追加する
HID Support | Input System | 1.0.2
NewInputSystemの入力元として、アセットとかで買ったサードパーティの入力APIを追加したいときについてです。
LeanTouchをNewInputSystemのタッチ入力として使うつもりで実装していきます。
Touchだけなら既に実装されていますが。
とりあえずコード
using System.Collections;
using System.Collections.Generic;
using Lean.Touch;
using UnityEditor;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Utilities;
#if UNITY_EDITOR
[InitializeOnLoad]
#endif
[InputControlLayout(displayName = "LeanTouch",stateType = typeof(LeanTouchState))]
[UnityEngine.Scripting.Preserve]
public class InputFromLeanTouch : InputDevice,IInputUpdateCallbackReceiver
{
public static InputFromLeanTouch current { get; private set; }
public static IReadOnlyList<InputFromLeanTouch> all => s_AllMyDevices;
private static List<InputFromLeanTouch> s_AllMyDevices = new List<InputFromLeanTouch>();
public ButtonControl button
{
get; private set;
}
public Vector2Control axis { get; private set; }
protected override void FinishSetup()
{
base.FinishSetup();
//引数のpath==構造体でInputControl属性のnameに一致するものが返り値になる
button = GetChildControl<ButtonControl>("button");//buttonにアクセスしやすいように
axis = GetChildControl<Vector2Control>("axis1");//axis1にアクセスしやすいように
}
/// <summary>
/// IInputUpdateCallbackReceiverの実装するべきメソッド
/// 今回のように、入力用のAPI(LeanTouch)が既にある場合
/// このメソッド内で値の更新をする
/// </summary>
public void OnUpdate()
{
var state = new LeanTouchState();
state.axis = LeanGesture.GetScreenDelta();
if (LeanTouch.Fingers.Count > 0)
{
state.buttons |= 1 << 0;
}
InputSystem.QueueStateEvent(this,state);
}
public override void MakeCurrent()
{
base.MakeCurrent();
current = this;
}
protected override void OnAdded()
{
base.OnAdded();
s_AllMyDevices.Add(this);
}
protected override void OnRemoved()
{
base.OnRemoved();
s_AllMyDevices.Remove(this);
}
static InputFromLeanTouch()
{
InitializeInPlayer();
}
[RuntimeInitializeOnLoadMethod]
static void InitializeInPlayer()
{
//このメソッドでInputActionアセットのBindingPathに反映される
InputSystem.RegisterLayout<InputFromLeanTouch>("LeanTouch");
//デバイスを追加するには下のメソッドを呼び出す
//InputSystem.AddDevice<InputFromLeanTouch>();
//今回の場合はLeanTouchがシーン内に置いてある必要があるので実行時にAwakeから呼び出す
//そのためのコンポーネントを別に作る必要があるので
//LeanTouchSupport.csを別に作る
}
}
//デバイスから取得する情報を構造体として定義する
//InputActionアセットで使うところのControlTypeとかバインドに使う名前
//値の型とか
public struct LeanTouchState : IInputStateTypeInfo
{
//何でもよいみたいです
//FourCCという識別する仕組みがあるみたい?
public FourCC format => new FourCC('L', 'T', 'T', 'O');
//InputControl属性
//nameはInputActionアセットのBinding➡Pathに表示される文字列
//bitは対応しているbitの列 ビットフラグでボタン状態の管理をしている
//layoutはInputActionのControlTypeに対応しているもの、だと思います
// layoutを省略した場合、フィールドの型から自動でそれなりに判別してくれるそう
[InputControl(name = "button",layout = "Button",bit = 0)]
public ushort buttons;//ushortは16bitなのでボタン16個分管理できる
[InputControl(name = "axis1",layout = "Vector2")]
//下のように書くと、axis1のXとYのそれぞれの軸について細かく設定できる模様
//何も書かなくてもaxis1.xとyは自動で追加されています
//細かい設定の引数については公式のドキュメントを
[InputControl(name = "axis1/x", defaultState = 0.0f, format = "FLT", parameters = "normalize,normalizeMin=-1,normalizeMax=1,normalizeZero=0.0,clamp=2,clampMin=-1,clampMax=1")]
[InputControl(name = "axis1/y", defaultState = 0.0f, format = "FLT", parameters = "normalize,normalizeMin=-1,normalizeMax=1,normalizeZero=0.0,clamp=2,clampMin=-1,clampMax=1")]
public Vector2 axis;
}
次のファイルはLeanTouchを持ったオブジェクトと一緒につけます。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Layouts;
/// <summary>
/// Leantouchを持っているオブジェクトにつける
/// </summary>
public class LeanTouchSupport : MonoBehaviour
{
private void Awake()
{
//このWithInterfaceというのがイマイチ理解できませんでした
//デバイスで使っているAPI(LeanTouch)と、自分が作ったデバイスを追加するスクリプト(InputFromLeanTouch)を
//対応させるために付けているのかも
//デバイスが削除されたとき(LeanTouchのオブジェクトが消されたときとか)に対応しているデバイスをまとめて削除するために
//付けているのかも
InputSystem.RegisterLayout<inputfromleantouch>(
matches:new InputDeviceMatcher().WithInterface("LeanTouch")); }
private void OnEnable()
{
//これでInputActionアセットを使って入力を取得することができる
InputSystem.AddDevice(
new InputDeviceDescription()
{
interfaceName = "LeanTouch",
product = name
});
}
private void OnDisable()
{
var device = InputSystem.devices.FirstOrDefault(
x => x.description == new InputDeviceDescription()
{
interfaceName = "LeanTouch",
product = name
});
if (device != null)
{
InputSystem.RemoveDevice(device);
}
}
}
</inputfromleantouch>
これで何とか最低限の実装は出来ました。値の設定については適当です。OnUpdate内を必要なように実装する必要があります。
ステップとしては
- 入力を受け取るデータを「構造体」として定義する
- InputActionアセットで表示する情報をInputSystem.RegisterLayout()を使って実装する
- InputSystem.AddDevice()を使って使うデバイスをInputSystemに登録する
のような感じになりました。
今回は新しくデバイスを追加しましたが、レイアウトを追加するだけなら別にやり方があるかもしれません。Touchのデバイス自体は標準で用意されているので、それに追加する感じで実装できたらもっと楽にできるのかも。
NewInputSystem自体の使い方はすでにいくつか情報がありますので省略しました。
別にそのままLeanTouchを使っても良いんですが、AndroidだけじゃなくSteamでも公開したいなと思っていたので、コントローラの差を吸収してくれるNewInputSystemを使ってみようと思いました。
InputActionを介して入力処理を実装すればとりあえず入力自体はInputActionアセットを変更するだけでよくなります。
理解できればそこまで大変ではないかもしれません。でも面倒は面倒です。使いまわせるように出来たら良いんですが。
コメント