アセット触ってみたシリーズ:多種多様なコントローラーに対応しよう!「Rewired」

みなさんはUnityで開発したゲームのPC版開発に興味はありませんか?
Unityユーザーの多くはスマートフォン向けのゲームアプリを作っていると思いますが、最近はSteamへPCゲームをリリースする日本のゲームクリエイターも増えてきています。
そんな時に考えなくてはいけないのは「コントローラー」への対応です。元がタップ操作中心のスマートフォンゲームであったならば、キーボードとマウス操作で十分かもしれません。しかしアクションゲームやRPGならば、コントローラー対応はほぼ必須と言えるでしょう。もちろん、Unityは標準でコントローラー入力に対応していますが、世の中に存在する多種多様なコントローラーに対応するためには、相応の作業が必要です。
そこで!今回はコントローラーを総合的に扱うことのできるアセット「Rewired」を紹介いたします。
あらゆるコントローラーを総合的に扱う「Rewired」
Rewiredは、Unityでコントローラーを使ったゲームを作るときに役立つ強力なサポートアセットです。世の中の標準的なPC向けコントローラーはもちろんのこと、いわゆるフライトシミュレーター向けの操縦桿コントローラーや、音ゲー用のギター型コントローラーにも対応しています。
RewiredはUnity Inputシステムの単なるラッパーではなく、Windows 10 ユニバーサルアプリや、PS4, Xbox Oneなどのコンソールゲーム機向けにはネイティブ対応をしています。
ソースを見る限りではdefineとして切っているだけかもしれませんが、ニンテンドー3DSとNintendo Switchにも対応しているようです。
また、マルチプレイヤーゲーム向けの複数コントローラーの入力制御についても、分かりやすく実装することができます。ゲームを動作させながらコントローラーを抜き差し(プラグアンドプレイ)しても大丈夫な設計になっています。
そして、ゲーム内のシーンによってボタンのアサインが変わる場面にも対応するシステムを備えています。一般的なアクションゲームでも、スタート画面、メニュー画面、ゲーム本編などでボタンの挙動は変わりますよね。こうした場面ごとの制御が格段に楽になります。
ただし高機能ゆえ、使いこなすにはそれなりの設定が必要になります。本稿ではRewiredのインポートから、主要な機能が使えるようになるまでの手続きについて紹介します。
Rewiredのインポート
まずはアセットストアからRewiredのパッケージをインポートしましょう。
インポートすると、まず公式ドキュメントについてのポップアップメッセージが現れ、次に別のメッセージが表示されます。
これは、InputManager.assetにRewiredが入力を制御するための情報を追加しますよ、という意味です。上書きされるわけではなく元ファイルはバックアップを作成してくれるそうなので、Addして問題ありません。既存のプロジェクトにRewiredを導入するときは気をつけましょう。
次に、「Control Mapper」を使うか否かを確認するメッセージが現れます。
後からインストールすることもできますが、大きなファイルではないのでインストールしておきましょう。
まだダイアログは続きます。スマートフォン向けの設定をインストールするか否かを確認するメッセージが現れます。
もしあなたがスマートフォンにも対応したゲームを作っている場合は、このパッケージをインストールする必要があります。最後にドキュメントをインストールするか否かかを確認するメッセージが現れますので、これもInstallを選んでおきましょう。
一連の手続きの途中で間違ってキャンセルしてしまった場合は、Window -> Rewired -> Setup -> Run Installerから再開できますので、各コンポーネントが後から必要になった場合は確認してみてください。
Rewiredの初期設定
まずは当該のシーンにRewiredを管理するゲームオブジェクトを作成します。Window -> Rewired -> Create -> Input Managerを選択します。
このゲームオブジェクトのインスペクターを確認するとDontDestroyOnLoadのオプションが付いています。基本的にゲーム中はずっと存在し続ける必要があるゲームオブジェクトです。
ゲームオブジェクトを作ったら、「Launch Rewired Editor」をクリックして各種設定をしていきます。全体的な流れは次の通りです。
- Players設定….ゲーム内のプレイヤーを作成。マルチプレイなら複数人。
- Actions設定….「左右移動」「パンチ」「決定」「キャンセル」などゲーム中で呼び出すアクション名を設定。
- JoyStickMaps設定….コントローラー、キーボードの入力とActionsを紐づける作業。
- もう一度Players設定…JoyStickMapsとPlayersを紐づける作業。
複数のレイヤーに分かれているため最初の一歩が遠く感じますが、順番に乗り越えていきましょう!
PlayerとActionを作成
沢山のオプションがありますが、まずは「Players」ボタンをクリックしてPlayersタブを開きます。
開いたら左下のNewをクリックして新規のプレイヤーを作成します。
「Player0」が新しく追加されます。マルチプレイの場合はここで人数分Playerを作るのですが、今回は1人プレイとして作っていきます。
次に「Actions」ボタンを設定します。Rewiredで言うActionとは、スクリプトからコントローラーの操作を検出したいときに指定する名前のようなものです。「左右移動」「パンチ」「決定」「キャンセル」などがこれに当たります。
「Actions」ボタンを押してタブを表示し、先ほどと同じようにNewからActionを作っていきます。
上の例ではテストとして、移動系のMove Horizontal・Move Verticalとボタン入力のShotを設定します。
Move Horizontalはスティック操作を取得するAxis入力です。取得できる値は-1.0から1.0までのfloat値となります。
まずはスティックの横入力を検出するMove Horizontalを作ります。
右端中央のドロップダウンメニュー「Type:」からAxisを選び、NameにMove Horizontal, PositiveにMove Right, NegativeにMove Leftと記入して下さい。
同様に縦入力として、Move Verticalの場合はPositiveがMove Forward, NegativeがMove Backです。
次にボタン入力のActionを作ります。Shotはボタン押し操作になります。TypeドロップダウンメニューからButtonを選んで、NameにShotを設定してください。
コントローラー入力にActionを割り当てる
Actionにはコントローラー、キーボード、マウスの入力値を割り当てることができます。タブから「JoyStickMaps」を選択するとRewiredで利用できるコントローラーの一覧が表示されます。
まずは、一般的なPC用コントローラーでの設定を想定して0番の「Dual Analog Gamepad」を選び、Create Mapをクリックします。
ここでActionとJoyStickの紐づけを行います。
「Create Defaults」をクリックすると、Elementに標準的なボタン入力の一覧が読み込まれます。
Elementの中から設定したいコントローラー入力項目を選択し、右端の「Action」を選びます。このボタン・スティックの入力があったときに、何のアクションを発行するかを紐づけていきます。
次の例ではLeft Stick XにMove Horizontalを、Left Stick YにMove Verticalを、Action Button Row 1にShotを割り当てました。
キーボード入力にActionを割り当てる
続いて、キーボード入力に割り当てを行います。右上のKeyboard Mapsを選択して下さい。
設定はJoyStickの場合とほとんど同じで、「Create Map」をクリックし、キー要素を作っていきます。
「Poll for Key Press」をクリックすると、そのあとに入力したキーを選択するモードに入ります。いちいちキーをドロップダウンボックスから選択することなく、楽にElementを埋めていくことができます。
こちらも例としてWASDにMove、スペースにShotを割り当てました。Move Horizontal / VerticalのActionはAxis入力ですが、それをキーボードやボタンに割り当てることも可能です。その場合は右端のAxis Contributionに、そのボタン入力がAxisの正方向になるのか負方向になるのかを選んでおきます。
Playerに入力設定を割り当てる
コントローラー設定、キーボード設定の2種類の入力設定が組みあがったら、最後にPlayerに対してそれらの設定を割り当てます。
左上のPlayersボタンをクリックし、最初に作成した「Player0」を選択して「Add Joystick Map」をクリックします。
次に「KeyBoardMaps」をクリックして、先ほど作成したキーボード設定を同様にPlayer0に割り当てます。
これで、初期設定は完了です!
実際にキャラクターを動かしてみる
ここまでの手続きで、コントローラーを使用するためのセットアップが完了しました。
実際にスクリプトの中で入力をフックする方法について解説します。RewiredのAPIは標準のInputシステムとよく似ています。
標準のボタン入力システムでは、まずUnity エディタのProject Settings -> Inputでスクリプト中の入力の名前とコントローラーボタンを紐づけてから、Update関数内で次のように記述します。
void Update()
{
if (Input.GetButtonDown("Shot"))
{
//弾の発射処理
}
}
Rewiredの場合、入力はPlayerごとに分かれています。
まずは入力を検出したいPlayerの参照を取得してから、Update内で入力判定を行います。
using Rewired;
~~一部略~~
private Player player0;
void Start()
{
player0 = ReInput.players.GetPlayer(0);
}
void Update()
{
if (player0.GetButtonDown("Shot"))
{
//弾の発射処理
}
}
ReInput.players.GetPlayer(0)から0番のプレイヤーの入力情報を取得できます。
player0として参照を保存してUpdate()内で利用しています。
同様に、移動系の入力はAxisの値をfloatで取得します。
次の例はRigidbody.AddForce()でキャラクターを操作する例です。
void Update()
{
float horizontal = player0.GetAxis("Move Horizontal");
rigidBody.AddForce(Vector3.right * horizontal * speed);
float vertical = player0.GetAxis("Move Vertical");
rigidBody.AddForce(Vector3.forward * vertical * speed);
}
このあたりもUnity標準と似ていますね。
方向キー入力と1種類のボタン入力のみでキャラクターが動くテストプログラムを作ってみましたが、特に違和感なく動作しました。
豊富なインプット検出
ボタン入力を検出する際、UnityではGetButton, GetButtonDown, GetButtonUpが利用できます。GetButtonはそのボタンが押されている間trueを返し、GEtButtonDownの方は押された瞬間だけtrueを返すものですね。
RewiredのAPIはこの基本の3種類に加えて、かなり豊富な入力検出機構を持っています。
2連打を検出する「GetButtonDoublePressDown」、2連打目に指を話さない状態の「GetButtonDoublePressHold」、長押し検出の「GetButtonLongPress」や何秒押し続けているかfloatを返す「GetButtonTimePressed」など豊富な取得オプションがあります。
非常に豊富なのですべては紹介しませんが、ゲームに頻出のパターンはほぼ網羅されているようです。
また、Player.AddInputEventDelegate()を使ってイベントを登録する形でボタン入力を設定することもできます。
これまでInput周りはタイミングやカウンターだらけの制御だったかもしれませんが、Rewindを使えばかなりすっきりしそうです。
カテゴリーの概念とその切り替え
Rewiredには「Category」という概念があります。
一つのゲームの中でも、コントローラーの入力とアクションが変わる瞬間があります。
たとえばメインのゲーム中と、メニュー画面と、ダイアログ表示中とではボタンの挙動が変わりますよね。そうした状況に対応するのが「Category」です。
ゲーム中にダイアログを表示する処理について考えてみます。
アクションゲームの進行で、なにかダイアログを出したときは「Category」を変更して入力を制御します。
ためしに「Map Categories」でダイアログ操作時の「System」というカテゴリーを新規作成し、このカテゴリー時のJoyStickMapsを作ってPlayerに追加します。
このとき、追加したJoyStickMapではStart Enabledのチェックを外し、ゲーム開始時は無効にしておきます。
ゲーム中でCategoryを切り替えるスクリプト操作は次の通りです。
private Player player0;
void Start()
{
player0 = ReInput.players.GetPlayer(0);
}
public void OnMenu()
{
player0.controllers.maps.SetMapsEnabled(false, "Default");
player0.controllers.maps.SetMapsEnabled(true, "System");
}
OnMenu()が呼ばれたときにDefault Categoryが無効化され、System Categoryが有効化します。こうするとSystem Categoryに記述された操作だけを受け付けるようになります。
ダイアログを出したときに切り替えをやってみましたが、このときDefault側に設定されているスティック入力は入らなくなり、攻撃ボタンだった X ボタンが System側に設定されている「決定」ボタンの入力として動作するようになります。
コントローラーの挙動が変わるときに、操作される側のステート管理などが必要なくなるわけです。
複数のコントローラーを使う
手持ちのコントローラーを色々引っ張り出して確かめてみました。
コントローラーごとにボタン配置は異なりますが、JoyStickMap設定をしっかり作ってあげれば問題なく動作します。
Unityの標準システムでは、どんなコントローラーが接続されたか名前を取得する「Input.GetJoystickNames」関数がありますが、これが非常にざっくりでDual Shock 4をつないでも「Wireless Controller」とか表示されたりします。Rewiredの場合は、一通りのコントローラーは認識します。
また、Rewiredが素晴らしいのは複数のコントローラーを同時に扱うことができる点です。
初期設定で「Player」を作成していましたが、これをプレイヤー人数分作成することでマルチプレイゲームの入力制御スクリプトがかなりシンプルになります。
まとめ
本稿ではRewiredの特徴と利用方法までを解説しましたが、まだまだ便利な機能が多く、網羅しきれていません。たとえば、いわゆるゲーム内での「ゲームパットコンフィグ」を可能にする機能や、Unity UIのイベントシステムと併用できる「Rewired Standalone Input Module」などがあります。ややアドバンスドな内容になってしまいますが、需要があればもう少し踏み込んだ紹介記事もやってみたいと思います。いかがでしょうか?
自作ゲームでSteam進出、コンシューマゲーム機への進出を考えているみなさま、Rewiredの導入をぜひ一度検討してみてください。
この記事を書いた人
一條貴彰株式会社ヘッドハイ 代表取締役
ゲーム作家・Game DevRel。小規模ゲーム開発者がもっと活躍できる世の中作りを目指して、ゲーム開発ツール・サービス専門のDeveloper Relation事業を行っています。ゲーム作家としての代表作は『Back in 1995』(Steam)。