デバイス単位で使う入力を分ける

山村達彦氏(以下、山村):ここからさらにややこしい話をしていこうと思います。次は何をやるのかというと、キャラクターの向きを変更する時に、どういうふうにやればいいのかという話をしていきます。

今、キャラクターは2つの操作形態で動いています。1個目が、スティックのそのままの入力で動かしているタイプ。もう1個が、マウスの位置を基にキャラクターの向く方向を決定するタイプ。これらが混在しているケースがあると、デバイスによって操作形態がまったく違う場合、非常に面倒くさくなってきます。

何をやるのかというと、Schemesを使って、デバイス単位で使う入力を分けてしまいます。例えば、スティックの方向を向く場合はGamepadというSchemesに。マウスの位置を狙うのはKeyboard & MouseというSchemesに所属させます。

今回は、有効なデバイスごとに、使わないデバイスのSchemesは止めてしまう。つまり、イベントの登録だけはしておくけれど、イベントの発行元をSchemes単位で止めてしまう。そういうことをすることで、まったく性質の異なる2つの系統の入力デバイスを同時に設定できるということをやっていきます。

AimとLookの作成

まずはAimとLookを作りましょう。Aimが「マウスで狙い撃つ」というもので、Lookが「スティックで狙い撃つ」みたいな感じ。AimはマウスでValue。

(Control Typeを)Vector 2にして(Pathを)Position。

これでマウスの位置を狙い撃ちます。Lookは(Control Typeが)Vector 2で、マウスではなく、GamepadのRight Stick(で狙い撃ちます)。

このタイミングでSchemesを作ります。

1個目がKeyboard & Mouse。この2つのどちらかを使っていれば、このSchemesを使う。もう1個(のSchemes)がGamepadで、こちらはGamepadのものを使います。

どちらのデバイスを使うのかはSchemesで設定します。LookはGamepadで、Aimはキーボード。

ほかのものもちゃんと設定しておきます。次はAimとLookのコードを書いていきます。ただ、そろそろ面倒になってきたので、チートシートからコピペしていきます。AimとLookのイベントを登録して、メソッドの中身も登録します。

Lookのメソッドは単純に、スティックの座標とベクトルを足したものの方向を向くというもので、Aimのメソッドはマウスの位置に対して視点を向けるというものです。そうすると、キャラクターがマウスの方向に視点を向けています。

これは今Gamepadで動かしていてマウスの位置が右上にありますが、マウスの方向を無視してGamepadのスティックでキャラクターを動かすと。

このSchemesですが、基本的にはAuto-Switchにチェックが入っていると、現在使われている一番新しいデバイスを採用します。

だから、例えばGamepadを動かしている時にキーボードを押せばキーボードが使われるし、キーボードを押している時にGamepadを触れば、GamepadのSchemesが選択されます。

これをやめたい場合、例えばGamepadしか使いたくない場合は、Default Schemeで設定した上で、Auto-Switchのチェックを外しておくとマウスが反応しなくなります。

動かない時はいつもビクッとしますね(笑)。これでマウスを動かしてもスティックは反応しませんが、Gamepadを動かすと普通に動きます。操作体系がぜんぜん違う場合は、状況や目的に応じてこういう感じでアクションを分けてしまって、使っているデバイスごとにどういうアクションを使うのかを設定してあげれば、いろいろなデバイスを切り替えられます。

戦闘モードと探索モードの作成

実はこの子は戦闘モードと探索モードがある設定なので、次はそれも作っていこうと思います。基本的に使うのはAction Mapという機能です。今までは、この戦闘モード操作の中に移動やUIナビゲートを突っ込んで、内部でステートを見て(動作を)分ける感じになっていました。

しかしそうではなく、例えば通常モードなら、移動とジャンプと決定。戦闘モードなら移動と回避と攻撃みたいに、Action Mapごと操作を切り替えてしまう。

その上で、例えば通常モードか戦闘モードかを切り替えれば、どれを使うのかというイベントの発生自体をなくしてしまう。これによって、Action Mapのモードを切り替えるだけでどれを使うかを切り替えられる、ということをやってみます。

もう1個Action Mapを作って。移動はこちら(のAction Map)にもあり、Dashはノーマルに持っていきます。

これで戦闘モードは射撃と狙い撃ちができますが、通常モードは移動とダッシュと、(なにもしない)アクションができる、というモードを設定しておきます。

コードの処理で、モードの切り替え先の挙動を切り替えてしまいます。1個だけ問題があります。今、Moveは(戦闘と通常モードの)2つあります。どちらを使うのかという話で曖昧になってしまうのはよくないので、Action Mapの単位でイベントを取得して設定しておきます。

いったんコードはリストラして、まずAction Mapを取得して、ノーマル(通常モード)のMoveに対してこんな感じのこと(OnMoveを登録)をしていきます、というコードが右側にあるのでコピーしましょう。

ノーマルモードとバトルモードの切り替え

それと、ノーマルモードとバトルモードの切り替えをイベントを作ってやっていきます。まず、モードの切り替えのイベントと、通常モードの移動。移動方法に対して先頭を向けるというやつです。

あと、モードが切り替わった時になにもないのがちょっとかわいそうなので、わかりやすくテキストで表示しましょう。モード切り替えのタイミングでテキストが呼ばれて、処理や移動をします。

大事なことが1個あって、Action Mapを切り替える処理というのがSwitchCurrentActionMapになります。ノーマルだったやつをバトルにして、バトルだったやつをノーマルにします。

(モード切り替えのアクションを追加して)キーを設定していなかったので、モード切り替えは、マウスは右クリックにしよう。Gamepadは○ボタン。

説明が前後してしまいましたが、とにかくAction Mapを2つ作って、ボタンに応じてAction Mapの切り替えをやっています。バトルモードではマウスの位置を向いていて、通常モードだったら移動方向に対して先頭を向けるということができます。

今どちらのAction Mapを使っているのかというのかがパッと見わかりませんが、Open Input Debuggerで確認できます。このUserのActionsでバトルが有効になっていて、ノーマルが全部Disabledになっています。これで切り替えると、こんな感じで(EnableとDisableが反転します)。基本的にバトルモードはダッシュできなくて、通常モードは移動できます。

こんな感じで、バトルモードと通常モードで、現在のキャラクターができるアクションを設定していて、(例えば探索や壁を登る時とか、いろいろなステートを作った上で)その上でSwitchCurrentActionMapで(ActionMapを)切り替えてやれば、アクションを切り替えられます。

もしくは、今は完全に切り替えてしまっていますが、基本操作のAction Mapと、戦闘モードか通常モードかを(一部だけ)切り替えるAction Mapの使い方もできると思います。

これ(SwitchCurrentActionMap)を使った場合、現在アクティブな指定したステート以外はDisableにする挙動をしますが、個別に(InputActionを)EnableやDisableを切り替えられるようになっています。この上で必要なAction Mapだけを有効にして、それ以外は無効にすれば、もうちょっといろいろ柔軟にできるようになります。

(次回につづく)