はじめに
新しいInputSystemへの移行をReactivePropertyを用いて行います
新しいInputSystemそのままだと使いにくすぎる…
環境
Unity2020.2
従来のUnityEngine.Inputからの移行
InputAction自体がInputすべての汎用クラスなので
旧InputのInput.GetButton/Input.GetAxisと同様に使えるよう
3パターンに分けてReactivePropertyへ変換を行います。
- Button 旧:Input.GetButton(Down/Up)
- Delta 旧:Input.GetAxis(MouseX) 例マウスの移動量
- Axis 旧:Input.GetAxis 例Joystick,Horizontal
変換には今回作成した拡張メソッドを使用しています。
InputActionの設定
- Button
こちらはデフォルトで大丈夫ですがButtonにしておくとBindingがボタンのみ表示されます
Bindingには押したいボタンを
TriggerBehabiorにはPressAndReleaseを設定します
- Delta
こちらはデフォルトで大丈夫ですがAxisにしておくとBindingがAxisのみ表示されます
- Axis
ジョイスティックの場合はドリフトするのでDeadZoneを設定すると良いです。
キーボードからAxisを作成する場合1DAxisを行うと作成できます。
InputActionをReactivePropertyに変換する拡張メソッド
InputSystemExtension.cs
using System.Collections;
using System.Collections.Generic;
using UniRx;
using UnityEngine;
using UnityEngine.InputSystem;
public static class InputSystemExtension
{
public static ReadOnlyReactiveProperty<bool> GetButtonProperty(this InputAction inputAction)
{
return Observable.FromEvent<InputAction.CallbackContext>(
h => inputAction.performed += h,
h => inputAction.performed -= h)
.Select(x => x.ReadValueAsButton())
.ToReadOnlyReactiveProperty(false);
}
//Axis入力だと0等が反応しないためGetDeltaAxisPropertyのみの使用でもよさそうです
public static ReadOnlyReactiveProperty<float> GetAxisProperty(this InputAction inputAction)
{
return Observable.FromEvent<InputAction.CallbackContext>(
h => inputAction.performed += h,
h => inputAction.performed -= h)
.Select(x => x.ReadValue<float>())
.ToReadOnlyReactiveProperty(0);
}
//Delta入力はUpdate基準なのでUpdate基準に変換(主にマウスで使用)
public static ReadOnlyReactiveProperty<float> GetDeltaAxisProperty(this InputAction inputAction)
{
return Observable.EveryUpdate().Select(_ => inputAction.ReadValue<float>()).ToReadOnlyReactiveProperty(0);
}
}
テストコード
TestInput.cs
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UniRx;
public class TestInput : MonoBehaviour,IDisposable
{
[SerializeField]
private InputActionMap inputAction;
private ReadOnlyReactiveProperty<bool> attack = default;
//ボタンに変換したIReactivePropertyを公開
public IReadOnlyReactiveProperty<bool> Attack => attack;
private ReadOnlyReactiveProperty<float> mouseX = default;
//Mouseの移動量に変換したIReactivePropertyを公開
public IReadOnlyReactiveProperty<float> MouseX => mouseX;
/// <summary>
/// 2ボタンで-1 0 1出力
/// </summary>
private ReadOnlyReactiveProperty<float> horizontal = default;
//Mouseの移動量に変換したIReactivePropertyを公開
public IReadOnlyReactiveProperty<float> Horizontal => horizontal;
private void OnEnable()
{
inputAction.Enable();
}
private void OnDisable()
{
inputAction.Disable();
}
private void Awake()
{
attack =inputAction.FindAction("Attack").GetButtonProperty();
mouseX = inputAction.FindAction("MouseX").GetDeltaAxisProperty();
horizontal = inputAction.FindAction("Horizontal").GetAxisProperty();
}
private void OnDestroy()
{
Dispose();
}
public void Dispose()
{
inputAction?.Dispose();
attack?.Dispose();
mouseX?.Dispose();
horizontal?.Dispose();
}
}
Test.cs
using UnityEngine;
using UniRx;
using UniRx.Triggers;
public class Test : MonoBehaviour
{
[SerializeField]
private TestInput input;
private void Start()
{
input.Attack.Subscribe(x=>
{
if (x)
{
Debug.Log("GetButtonDown");
}
else
{
Debug.Log("GetButtonUp");
}
}).AddTo(this);
this.UpdateAsObservable().Subscribe(_ =>
{
Debug.Log("GetButton:" + input.Attack.Value);
Debug.Log("Horizontal"+ input.Horizontal);
Debug.Log("MouseX" + input.MouseX);
}).AddTo(this);
}
}
最後に
InputSystemPackageをそのまま使用するよりは楽に使えるようになったと思います。