はじめに
UnityのInputSystemは強力ですが、イベントベースのためUniRxと組み合わせてリアクティブに扱いたい場面が多くあります。
この記事では、InputActionを簡単にObservable化できる拡張メソッドを紹介します。
FromEventを使ってInputActionをObservable化
InputActionのstarted / performed / canceledはイベントなのでObservable.FromEventを使うと安全にRx化できます。
ポイント:
- UniRxが内部で例外処理をしてくれる
- イベント購読解除も安全に行える
- 読みやすく、チーム開発でも理解されやすい
完成コード
using System;
using UniRx;
using UnityEngine.InputSystem;
public static class InputActionRxExtensions
{
public static IObservable<InputAction.CallbackContext> StartedAsObservable(this InputAction action)
=> Observable.FromEvent<InputAction.CallbackContext>(
h => action.started += h,
h => action.started -= h);
public static IObservable<InputAction.CallbackContext> PerformedAsObservable(this InputAction action)
=> Observable.FromEvent<InputAction.CallbackContext>(
h => action.performed += h,
h => action.performed -= h);
public static IObservable<InputAction.CallbackContext> CanceledAsObservable(this InputAction action)
=> Observable.FromEvent<InputAction.CallbackContext>(
h => action.canceled += h,
h => action.canceled -= h);
}
実際の使用例
using UniRx;
using UnityEngine;
using UnityEngine.InputSystem;
public class Test : MonoBehaviour
{
[SerializeField] private InputAction _jumpAction;
private void Awake()
{
_jumpAction.Enable();
_jumpAction
.PerformedAsObservable()
.Subscribe(_=>
{
Debug.Log("Jump");
})
.AddTo(this);
}
}
まとめ
-
InputActionのイベントはFromEventで安全にRx化できる
-
UniRxと組み合わせることで入力処理がシンプルになる
おまけ
FromEventを使う方法より柔軟ですが、例外処理などは自前で実装する必要があります。
private static IObservable<InputAction.CallbackContext> ToObservable(
Action<Action<InputAction.CallbackContext>> add,
Action<Action<InputAction.CallbackContext>> remove)
{
return Observable.Create<InputAction.CallbackContext>(observer =>
{
Action<InputAction.CallbackContext> handler = observer.OnNext;
add(handler);
return Disposable.Create(() => remove(handler));
});
}
public static IObservable<InputAction.CallbackContext> StartedAsObservable(this InputAction action)
=> ToObservable(
h => action.started += h,
h => action.started -= h);
public static IObservable<InputAction.CallbackContext> PerformedAsObservable(this InputAction action)
=> ToObservable(
h => action.performed += h,
h => action.performed -= h);
public static IObservable<InputAction.CallbackContext> CanceledAsObservable(this InputAction action)
=> ToObservable(
h => action.canceled += h,
h => action.canceled -= h);