はじめに
UniRxやR3を使用してInputSystemをスクリプトから操作する方法を調べてみても調べ方が悪いのかInputManagerを使用している実装方法しか見つかりませんでした。
UniRx、R3を普段から使用している方やInputSystemをスクリプトから操作している方でプレイヤーの入力をUniRx、R3で分かりやすく、使いやすくしたい方に向けて、今回はUniRxの後継であるR3を使用してInputSystemをスクリプトから操作し、プレイヤーの移動を実装してみようと思います。
InputSystemの作成
まずはInputSystemでActionを登録します。今回は新しく作成しました。すでに作成している方は読み飛ばして次に進みましょう。
今回はスクリプトからInputSystemを操作するのでActionMapを選択中にInspectorに表示されているGenerate C# Class にチェックをしておきましょう。
InputActionsの内容はこんな感じです。Moveを登録しました。実際はジャンプなどもあると思うので各々追加してみてください。
PlayerInputProviderの作成
InputActionsが作成できたら次は入力を検知するスクリプトを作成します。先ほど作成したInputActionsを直接生成します。他には、移動とジャンプの入力を検知するプロパティを作成します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using R3;
public interface IPlayerInputProvider
{
public R3TestInput R3InputAction { get; }
public ReadOnlyReactiveProperty<Vector2> Move { get; }
public ReadOnlyReactiveProperty<bool> Jump { get; }
}
次にIPlayerInputProvider.csを継承したR3PlayerInputProviderを作成します。InputSystemで登録したMoveに関数を設定しておきましょう。
InputSystemはEnable()をしておくこと、破棄されるときにはDispose()しておきましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using R3;
using UnityEngine.InputSystem;
internal sealed class R3PlayerInputProvider : MonoBehaviour, IR3PlayerInputProvider
{
public R3TestInput R3InputAction => _R3inputAction;
public ReadOnlyReactiveProperty<Vector2> PlayerMove => _playerMove;
private R3TestInput _R3inputAction;
private readonly ReactiveProperty<Vector2> _playerMove = new();
// Start is called before the first frame update
void Awake()
{
_R3inputAction = new R3TestInput();
_R3inputAction.Player.Move.performed += OnMove;
_R3inputAction.Player.Move.canceled += OnMove;
_R3inputAction.AddTo(this);
_R3inputAction.Enable();
_playerMove.AddTo(this);
}
void OnDestroy()
{
_playerMove.Dispose();
_R3inputAction.Disable();
_R3inputAction.Dispose();
}
private void OnMove(InputAction.CallbackContext context)
{
_playerMove.Value = context.ReadValue<Vector2>();
}
}
プレイヤー移動スクリプトの作成
次に先ほど作成した入力システムを使ってプレイヤーが移動するスクリプトを作成します。この記事では移動したらログを出すサンプルですが、購読しているログのところに移動する関数や移動スピードを設定してあげれば動くと思います。
R3PlayerInputProviderをアタッチしないと動かないのでつけ忘れないようにRequireComponentを設定しておきましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using R3;
[RequireComponent(typeof(R3PlayerInputProvider))]
public class R3playerMoveTest : MonoBehaviour
{
private R3PlayerInputProvider input;
// Start is called before the first frame update
void Start()
{
input = GetComponent<R3PlayerInputProvider>();
// 移動するキーが押されたらログを出す
input.PlayerMove.Where(x => x.magnitude > 0.5f).Subscribe(_ => Debug.Log("MOVE!"));
}
}
では実際にSphereにR3playerMoveTest.csをアタッチして動かしてみましょう。R3playerMoveTest.csにはクラス名の上にRequireComponentが設定されているのでR3PlayerInputProviderは自動で追加されます。実行してWASDを押してみるとログが出力されると思います。
もし動かないという方はInputSystem側の設定などを確認してみましょう。他にも入力を検知した際に値をうまく取得できていないとログが出力されないのでこちらも確認してみましょう。
まとめ
いかがでしたか?これで使いやすいInputSystemをRniRxやR3で使いやすくすることができるようになったと思います。PlayerInputコンポーネントでInspectorからセットして使うこともできますが、うまく動かない原因として関数をセットしていないのか自分が作成したスクリプトが良くなかったのか分かりにくいのでぜひUniRxなどを普段から使用している方はこの方法で使用することをおすすめします。