Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8899

New Input System をふわっと理解する ~大八耐2019 in Tokyoを添えて~

$
0
0

まえがき

 大八耐2019 in Tokyoに参加したときに気になっていたNew Input Systemを触ってみたのでふわっとまとめたみました。

*Input System - 1.0.0 時点での記事なので以降のバージョンと差異がある可能性があります。

Input System のインストール

 Input SystemはPackage Managerを通じてインストールします。
 *2019年11月時点では、まだpreview packageなのでShow preview packagesにチェックを入れないとリストに現れません。
スクリーンショット 2019-11-12 16.31.09.png
 次に、Project Settings > PlayerからActive Input Handlingを設定します。設定を反映させるにはUnity Editor の再起動が必要なので注意しましょう。
スクリーンショット 2019-11-12 16.40.14.png

Input Settings を作る

 次は、Project Settings > Input System Package からCreate settings assetを選択し、InputSystem.inputsettingsを作成します。
スクリーンショット 2019-11-12 17.37.55.png

 作成したInputSystem.inputsettings からOpen Input Setting Windowを選択し、Supported Devicesに入力を取りたいデバイスを登録します。
スクリーンショット 2019-11-13 16.17.18.png

Input Actionを使ってみる

 Input Actionは、入力があった際のイベントをデリゲートに登録しておくことで動作します。今回は、キーボードのスペースキーとスクリーンのタップと、マウスとタップの座標を取得してみます。
スクリーンショット 2019-11-14 22.24.06.png

GettingFromDevice.cs
usingUnityEngine;usingUnityEngine.InputSystem;publicclassGettingFromDevice:MonoBehaviour{[SerializeField]privateInputAction_jumpInput=default;[SerializeField]privateInputAction_moveInput=default;privatevoidAwake(){// A事前にイベントを登録しておく_jumpInput.performed+=callbackContext=>{// Buttonの入力はfloatvarvalue=callbackContext.ReadValue<float>();if(value>0){Debug.Log("On Jump.");}};_moveInput.performed+=callbackContext=>{varvalue=callbackContext.ReadValue<Vector2>();Debug.Log($"position {value.x},{value.y}");};}privatevoidOnEnable(){// Enable()で有効化しないと動作しない_jumpInput.Enable();_moveInput.Enable();}privatevoidOnDestroy(){_jumpInput.Dispose();_moveInput.Dispose();}}

 InputActionフィールドを定義し、インスペクタで各InputActionにBindした入力受けたときのイベントをInputAction.performedに記載します。この時InputAction.Enable()で有効かしておかないと動作しないので注意が必要です。
 CallbackContext.ReadValueで受け取る値は、インスペクタ上の各InputActionの歯車ボタン内のAction TypeとControl Typeから設定しています。
今回の例では、Jump InputはAction TypeはButton、Move InputはAction TypeはValue、Control TypeをVector2としています。

スクリーンショット 2019-11-14 22.32.46.png
スクリーンショット 2019-11-14 22.34.17.png

 ActionをButtonにした場合は、Control Typeはfloatになっています。

 キーボードのWASDをなど複数のキーを入力として取りたい場合、Add BingindではなくAdd 2D Vector Compositeを使います。上下左右のにそれぞれのキーをBind
することでVector2の入力を作ることができます。ただしMouseのPositionとは異なり座標ではなく-1から1の正規化された入力なので併用する場合は工夫が必要です。

スクリーンショット 2019-11-14 22.39.40.png

ActionMapを生成してみる

 先ほどは、InputActionフィールドを用意してデリゲートにイベントを登録しました。今度はActionMapを生成し、自動生成されたコードを継承してコールバックを受け取る方法を試してみます。先ほどと同じくキーボードのスペースキーとスクリーンのタップと、マウスとタップの座標を取得してみます。
スクリーンショット 2019-11-14 22.56.02.png
 Asset > Create > Input ActionsからSampleControles.inputactionsを生成し、SampleMapsの中に先ほどと同じくMoveActionとJumpActionをを設定しました。次にGeberate C# Classにチェックを入れてApplyすると同じフォルダに同名のクラスが生成されます。今度はこれを動かすコードを書いていきます。

ActionMapSample.cs
usingUnityEngine;usingUnityEngine.InputSystem;// 生成されたクラスはI[ActionMap]インターフェスを持っているので、これを実装します。publicclassActionMapSample:MonoBehaviour,SampleControls.ISampleMapsActions{privateSampleControls.SampleMapsActions_sampleMapsActions=default;privatevoidAwake(){// SampleControlsに登録したActionMapを生成ます。_sampleMapsActions=newSampleControls.SampleMapsActions(newSampleControls());// SampleControls.ISampleMapsActionsが実装されたクラスをSetCallbacksに指定します。_sampleMapsActions.SetCallbacks(this);}// SampleControls.ISampleMapsActionsによって定義されたMoveActionのコールバックpublicvoidOnMoveAction(InputAction.CallbackContextcallbackContext){varvalue=callbackContext.ReadValue<Vector2>();Debug.Log($"position {value.x},{value.y}");}// SampleControls.ISampleMapsActionsによって定義されたJumpActionのコールバックpublicvoidOnJumpAction(InputAction.CallbackContextcallbackContext){varvalue=callbackContext.ReadValue<float>();if(value>0){Debug.Log("On Jump.");}}privatevoidOnEnable(){// 忘れずEnabl()_sampleMapsActions.Enable();}privatevoidOnDestroy(){// こっちはDisposeではなくDisable()_sampleMapsActions.Disable();}}

 自動生成されたクラスはファイル名.I[ActionMap名]のインターフェースを持っています。これを実装したクラスをSetCallbacksで指定することで入力を取得できるようになります。この時、ReadValueで取得する型とControl Typeが一致していないとエラーになってしまいます。

入力の検知タイミングを指定する

 これまでJumpActionとしてキーボードやタップを入力にしましたが、現在の状態では押した時、離した時の両方で入力を受け取ってしまいます。これを回避するためにInteractionsを設定する必要があります。
スクリーンショット 2019-11-14 23.39.28.png
 上記のようにJumpActionのInteractionsにPressを、そしてTrigger Behavior
nにPress Onlyを設定しました。これによってJumpActionはButtonのPressのみを検知するようになりました。今回はJumpActionに対して設定しましたが、SpaceキーやTouchそれぞれ個別に設定することも可能です。

 *ここまで実装した方は気づいたかもしれませんがNew Input Systemは1フレームに複数回の入力を受け取ることができます。フレームに依存しないので処理落ち処理落ちした場合でも入力を受け取ることができますが、同じ処理を複数回しないために工夫する必要があります。

大八耐2019 in Tokyo

 大八耐2019ではパズルのピースを使ったテトリスっぽいものを作ってみました(完成しませんでした)。ピースを回転させて横一列に並べるというミニゲームで、New Input Systemを使ってキーボード入力からピースを左右に回転させました。
スクリーンショット 2019-11-14 23.53.12.png

SpinInputView.cs
usingSystem;usingpapicra.Scripts.Presentation.Presenter;usingUniRx;usingUnityEngine;usingUnityEngine.InputSystem;namespacepapicra.Scripts.Presentation.View{publicclassSpinInputView:MonoBehaviour,PieceRollControls.IPieceRollActionActions,ISpinInputPort{privatePieceRollControls.PieceRollActionActions_input=default;privatereadonlySubject<Unit>_spinClockwise=newSubject<Unit>();privatereadonlySubject<Unit>_spinUnClockwise=newSubject<Unit>();publicIObservable<Unit>OnSpinClockwise()=>_spinClockwise.Publish().RefCount().ThrottleFrame(1);publicIObservable<Unit>OnUnSpinClockwise()=>_spinUnClockwise.Publish().RefCount().ThrottleFrame(1);privatevoidAwake(){_input=newPieceRollControls.PieceRollActionActions(newPieceRollControls());_input.SetCallbacks(this);}publicvoidOnClockwise(InputAction.CallbackContextcontext){if(context.ReadValue<float>()>0){_spinClockwise.OnNext(Unit.Default);}}publicvoidOnUnClockwise(InputAction.CallbackContextcontext){if(context.ReadValue<float>()>0){_spinUnClockwise.OnNext(Unit.Default);}}privatevoidOnEnable(){_input.Enable();}privatevoidOnDestroy(){_spinClockwise?.OnCompleted();_spinClockwise?.Dispose();_spinUnClockwise?.OnCompleted();_spinUnClockwise?.Dispose();_input.Disable();}}}

 その時に使用したコードがこちらです。テラシュールブログ様 *2 を参考に結構さっくりと実装ができました(inputsettingsの項目に気がつかなくて入力が取れず沼ったのは秘密)。今回紹介したInputActionフィールドを定義してデリゲートにイベントを登録する方法、ActionMapをつかったコールバックを取る方法、ここでは紹介していないPlayerInputを使う方法など色々ありますが、個人的にはコールバックを取る方法が一番やりやすいなぁと感じました。インターフェースあると実装漏れないし楽でした。
 大八耐の時間内でゲームを完成させることはできませんでしたがNew Input Systemを触るいい機会になったので個人的には大満足です。ゲーム自体はちまちま作っていこうかな。

あとがき

 大八耐2019 in TokyoにてNew Input Systemを軽く触ってみたのでまとめてみました。BindingsやProcessorsなどなど調べ切れていないことが多々あるのでまたいずれ......。
 内容に誤りがありましたら、@sai_maple_にご連絡いただけると幸いです。

参考

*1 Input System documentation
*2 テラシュールブログ


Viewing all articles
Browse latest Browse all 8899

Trending Articles