InputSystem のインストールと設定
PackageManager でInputSystem をインストール
PackageMagager を開きます。
Packagesで UnityRegistry を選択します。
Input System を選択し、Install ボタンを押します。
Input System を有効にするために、Unityエディタを再起動するか聞かれるので Yes を選択します。
Player のキャラクターに PlayerInput を取り付ける
Unityエディタの再起動が終わったら、Player キャラクターに PlayerInput を追加します。HumanMale_Character_Free を選択し、 Add Component ボタンを押します。
Input から Player Input を選択します。
アクションの定義ファイル作成
追加した Player Input コンポーネントから Create Actions ボタンを押して、アクションを作成します。
保存場所とファイル名を聞かれるので、適当に名前を付けてアクションファイルを保存します。今回は Assets 直下に、MyInputActions という名称で保存しました。
初期設定状態で次のようなものが定義されています。
DualShock の×ボタンを押したら走るようにしたいので、中央の列のActions の + ボタンを押しAction 名を Sprint として新しいアクションを登録します。このとき、Action Type を Pass Trough、Control Type を Button にします。
ここでAction Type を Button にすると、DualShock4 で正常に動作しなくなります。DualSense や XBox コントローラーなら、Action Type を Button にしても問題ありませんでした。
Sprint の下に GamePad の Button South と Left Shift を割り当てておきます。
修正が終わったら Save Asset ボタンを押して終了します。
Player Input の Actionsに 今作ったファイル名が登録されているはずです。このとき Behavior は Send Messages にしておきます。Send Message の場合、アクションに何か起こると、OnMove のように定義してあるアクション名の前に On が付いている関数が呼び出されます。
Send Message 以外の方法は後で説明します。
キャラクタの設定
キャラクタを操作して歩いたり走ったりできるようにするために、Character Controllerを追加し、アニメーションを設定していきます。
Character Controller の追加と設定
キャラクタの移動が可能になるように、HumanMale_Character_Free のコンポーネントに Character Controller を追加します。Inspecter から Add Component ボタンを押し、Physics を選択した後、Character Controller を選択します。
Character Controller に次のような値を設定します。
アニメーターコントローラの追加と設定
PlayerCharacter というフォルダを作成して、その中に Animator Controller を追加します。
作成したAnimator Controllerは、PlayerAnimatorController という名前にします。そして、
PlayerAnimatorController をHumanMale_Character_Free の Animator コンポーネントの Cotroller に設定します。(ドラッグアンドドロップ、または ⦿を押してPlayerAnimatorControllerを選択します。)
PlayerAnimatorController をダブルクリックして、Animatorの設定画面を開きます。
そうしたら Parameters を選択し、 +ボタンから Float を選択してパラメータを追加します。追加するパラメータ名は Speed にします。
続いて、Base Layer の開いているところで右クリックして、Create State から From New Blend Tree を選択して、BlendTreeを追加します。
追加した BrendTree の名前を Locomotion に変更します。
Locomotion をダブルクリックして BrendTree の設定を開きます。Inspecter の Motion の + ボタンを押して、 Add Motion Field で Motion を追加します。Add Motion Field を 3回実行します。
1個目のMotion の ⦿ を押して、Idle アニメーションを選択します。
同様の操作を繰り返して、WalkForward アニメーションと Sprint アニメーションを設定します。アニメーションの追加後に、Automate Thresholds のチェックを外し、Threshold の値を画像のように設定します。
スクリプトの追加
Assets フォルダに、スクリプトを置くための Scripts フォルダを作成します。
Scripts フォルダに、PlayerMove.cs を入れます。ファイルは、記事の後ろの方に添付してあります。
PlayerMove.cs を HumanMale_Character_Free のコンポーネントに追加します。(ドラッグアンドドロップ、または、Add Component から Scripts を選択して、PlayerMove.cs を選択します)
PlayerMove.cs
Player Input コンポーネントで、Behavior を SendMessages にした場合のスクリプトです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerMove : MonoBehaviour
{
CharacterController characterController;
PlayerInput playerInput;
Animator animator;
// 移動速度
private float walkSpeed = 2f;
private float sprintSpeedUpRatio = 4f;
private float rotationSpeed = 720f;
bool isRunning = false;
Vector2 input = Vector2.zero;
void Start()
{
characterController = GetComponent<CharacterController>();
playerInput = GetComponent<PlayerInput>();
animator = GetComponent<Animator>();
}
void Update()
{
var velocity = Vector3.zero;
// 方向キーの入力があったら、その向きにキャラクターを回転させる
if (input.magnitude != 0)
{
Vector3 playerDirection = Vector3.Normalize(new Vector3(input.x, 0, input.y));
Quaternion characterTargetRotation = Quaternion.LookRotation(playerDirection);
transform.rotation = Quaternion.RotateTowards(transform.rotation, characterTargetRotation, rotationSpeed * Time.deltaTime);
}
// 移動速度の計算
float speedByStick = input.magnitude;
float moveSpeed = walkSpeed * speedByStick;
if (isRunning)
{
moveSpeed *= sprintSpeedUpRatio;
}
velocity = transform.forward * moveSpeed;
// アニメーションの速度設定
animator.SetFloat("Speed", moveSpeed);
// キャラクターの移動
characterController.Move(velocity * Time.deltaTime);
Debug.Log("isRunnging : " + isRunning.ToString());
}
public void OnMove(InputValue value)
{
input = value.Get<Vector2>();
}
public void OnSprint(InputValue value)
{
isRunning = value.isPressed;
}
}
OnMove() と OnSprint() は、InputSystem からメッセージが送られてきて実行されます。
PlayerInput から CurrentActionMap を使って入力を読み込む方法
PlayerMove.cs の OnMove() と OnSprint() を消して、 Update() 内で以下の記述をしても、入力を読み込むことができます。
input = playerInput.currentActionMap["Move"].ReadValue<Vector2>();
isRunning = playerInput.currentActionMap["Sprint"].IsPressed();
Unity Event を使う方法
PlayerInput コンポーネントで、Invoke Unity Event を設定して、イベント経由で入力を読み込む方法もあります。
まず、 PlayerInput コンポーネントの Behavior で Invoke Unity Event を選択します。
PleyerMove.cs の代わりに、PlayerMove_event.cs をHumanMale_Character_Freeに取り付けます。
PleyerMove.cs との違いは、OnMove() と OnSprint() をコールバック関数に変えたところです。
public void OnMoveEvent(InputAction.CallbackContext context)
{
input = context.ReadValue<Vector2>();
}
public void OnSprintEvent(InputAction.CallbackContext context)
{
// ボタンの状態を調べるだけなら次の行だけでも良い
// isRunning = context.ReadValueAsButton();
// ボタンが押されたとき、離されたときで処理を書く場合次のように書く
switch (context.phase)
{
case InputActionPhase.Performed:
isRunning = true;
break;
case InputActionPhase.Canceled:
isRunning = false;
break;
}
}
ボタンの状態に対して柔軟にコードを書くことができます。
PlayerInput モジュールの Events の Player にそれぞれコールバック関数を設定します。
DualShock4 での動作
PS4 のコントローラである DualShock4 を使った場合、Action Type を Pass Trough、Control Type を Button にして、Send Message を使った方法しかうまく動きませんでした。(Control Type はAnyでも可)
Unity Event や playerInput.currentActionMap[“Sprint”].IsPressed(); を使った場合、また、Action Type を Button にした場合は、ダッシュボタンに設定した × ボタンを押しっぱなしにしているときに、他のボタンやスティックの入力があった場合、ボタンを離したという扱いになり IsPressed() などが false を返すようになります。
DualSense や XBos360 コントローラをつないだ場合はうまく動きます。
ファイル
おわりに
以上、InputSystem を使ったキャラクターの移動処理でした。