Input Systemが正式導入されて、二年ほど経つわけで今更なのですが、しばらくUnityに触ってなかった自分のような者にとっては、なかなか触りにくい新機能でした。
しかし、そうも言っていられず、最近ようやく触り始めていて、その素晴らしさに感激しているところです。もっと早くに触っておけばよかった!
今だからこそ言えますが、旧Input Managerは使い勝手も含めて本当に酷いものだったと思います。良くあんなのでみんなゲームを作っていたな!
そう思ってしまうくらいに新しいInput Systemは慣れてさえしまえば、非常に使いやすく分かりやすく管理しやすい入力デバイス管理システムになっています。
Input Systemについては本格的に記事を書きたいと思っていますが、その前にちょっとしたテスト記事を書いてみたいと思います。なので、細かい部分についてはあまり触れないようにしています。
Input Systemの設定
Input Systemの設定は非常に明快です。まずはInput Systemパッケージを導入する必要がありますが、今回はその工程は省きます。
Assetフォルダ下の適当な場所にInput Action Assetを作成し、専用エディターを開きます。各アクションをグループ分けするAction Mapを作成し、そこにアクションを追加し、それに実際の操作デバイスの各入力を結び付け(Bind)ていく、というのが基本です。
今回はマウスを使うので、MouseというAction Mapを作成します。そして、マウスのポジションを読み取るMousePosとRaycastを実行するCastRayというアクションを作成して、それぞれにPosition [Mouse]とLeft Button [Mouse]をバインドしました。
Position [Mouse]は二次元平面におけるx座標y座標なのでValueタイプのVector2を、マウスクリックは単純にボタンを押す情報だけなので、Buttonとなります。
このように入力情報の設定もここで簡単にできてしまうのです!めちゃくちゃ便利!!
マウスからビームを飛ばす
今回はInput Systemのテストとして、簡単なプログラムを作成しました。画面上のマウスポインタからRaycastを飛ばし、それに当たったオブジェクトの色を変えるというものです。
Physics.Raycastと言えば、Unityにおいてオブジェクトを検出するのに欠かせないメソッドの一つですが、発射するポイントと飛ばす方向が大事!
今回はスクリーン上にあるマウスカーソルの位置をワールド座標に変換し、それを元にRaycastして狙ったオブジェクトに当てる、というモノにします。
というわけで、そのスクリプトがコチラ!これをメインカメラに装着しています。
スクリプト上でInput SystemのAPIを利用する場合、using文にUnityEngine.InputSystemを追加する必要があります。
Input Systemで受け付けた入力情報と実際の処理を結び付ける方法はいくつかあり、それについては後日まとめたいと思います。
その中でも分かりやすく、安定択であろうPlayer InputというInputSystemパッケージで用意されているコンポーネントを利用する方法を今回は採用しています。
Add ComponentからPlayer Inputコンポーネントをゲームオブジェクトに装着することが出来ます。これをメインカメラに追加しました。
Default MapをMouseに設定し、Events項目にて各アクションとこのスクリプトにあるメソッドを繋ぎ合わせることが出来ます。その詳細もこの記事では省きます。
ReadMousePos :
スクリプト上ではマウスのスクリーン上の位置を読み取る。
Shoot :
Raycastを実行し、そこから検出したRaycastHit情報を元に狙ったオブジェクトの色を黄色にする。
この二つのメソッドをPlayer Inputに登録します。
PlayerInputからこれらのメソッドが呼び出されるときに、InputAction.CallbackContextというタイプのデータが渡されるので、きちんとそれも引数として書かないといけません。このデータから渡される情報を元に処理を進めるので重要です。
Camera.ScreenToWorldPosについて
今回、このスクリプトで少し詰まってしまった所があって、それはScreenToWorldPosというスクリーン上の座標をシーン内のワールド座標に変換するメソッドです。
Input System上のPosition[Mouse]というのは画面のピクセルの実数を返すのですが、自分としては解像度でそれを割った正規化した値をこのメソッドに入力するものとばかり思っていたのですが、そうではありませんでした。
position[Mouse]で得た値をそのままにVector3に変換して渡さないと上手くいきません。正規化しなくていいのか・・・とは思いましたが、それで上手くいくのだからしょうがないし、それでいいんでしょう。
とにかく、これでマウスのスクリーン上の座標をワールド座標に変換できました。
色を変える!
Renderer.material.SetColor()を使って、オブジェクトのマテリアルの色を変えていきます。今回のオブジェクトに使っているマテリアルはUnity URPの標準シェーダーである、Universal Render Pipeline / Litシェーダーを使用しています。よってメインカラーのプロパティは_BaseColorとなります。
そして、MeshRendererからマテリアルに触りにいくので・・・
meshRenderer.material.SetColor("_BaseColor", Color.yellow);
というような文になります。(画像のスクリプトではRaycastHitから直接GetComponentでアクセスしてますが)
raycastの撃ち方については工夫しており、カメラの位置を起点にして、そこからマウスのワールド座標(z座標は奥に移動させてる)に向けて打つ、ということにして、スクリーン上で狙ったオブジェクトに打てるようにしています。
そして、そこから帰ってきたRaycastHitからコライダーにアクセスし、GetComponentからMeshRendererにアクセスし、SetColorを実行します。
ちなみに、SetColorでの色指定を
.SetColor("_BaseColor", new Color(Random.Range(0.0f, 1.0f),
Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f)));
という風にすると、オブジェクトをクリックする度に色がランダムに変わるので、アプリケーションとしては、こちらの方が面白いですね。
まとめ
というわけで、新しいInput Systemを使って、マウス座標の獲得、およびレイキャストを打って狙ったオブジェクトの色を変える、というプログラムを作ってみました。
繰り返しますが、Input Systemは慣れてさえしまえば、旧Input Managerをはるかにしのぐ使いやすさを持ったシステムであります。Unity、ありがとう!
そして、Unityの新しい入門アセットである、StarterAssetでもInput Systemを採用しており、このアセットで学ぶことが出来ますし、自分も大いに助かりました。
Input Systemについては、後日改めて、きっちり書きたいと思います!!二年越しのInput Systemデビューでしたが、Unityは本当に良いソフトになってきていますね、やる気も上がります!