Top > ComputerGraphics > Unity > Tips > BasicInput
Last-modified: Tue, 21 May 2013 12:09:19 JST
Counter:56749 Today:1 Yesterday:4 Online:4
このエントリーをはてなブックマークに追加

Unityであつかわれる標準的な入力のサンプル

About

Unityでゲームやアプリケーションを開発する場合に必要となる、最低限の入力についてまとめておきます。解説は基本的には不要で、サンプルの挙動とソースコードとを見れば把握できるようにしているつもりです。よって必要な場合にだけ解説を読むことを推奨します。

0.png

[予備知識]ゲームにおけるユーザの入力について

多くのゲームはゲームループと呼ばれる繰り返し処理の中で進行します。一般にゲームループとは、キャラの移動や当たり判定、点数増減処理などに続き、最終的にレンダリング結果を画面に出力するまでの一連の流れを指し、1秒間に何度も実行されます。ゲームループが1回処理され、画面が1回描画されるまでの処理速度をにFPSと呼びます。つまりゲームなどでよく目にする60FPSとは1秒間にゲームループが60回実行され、60回描画されることを言います。※30FPSなら1秒間に30回、ふつう24FPS以上あれば動画に見えるとされます。

そこでゲームにおいて入力をあつかう場合には注意する必要があります。それは、ボタンを1度だけ押した、という入力の検出です。ゲームループは1秒間に何十回も実行されるわけですから、現実世界でプレイヤーが1回ボタンを押して離すまでの間に、ゲームループは何度か実行されてしまいます。そこで一般的なゲームの開発では、その入力が1回だけのものなのか、あるいは連続的な入力(ボタン押しっぱなし)なのか、を判定する処理を実装する必要があるわけです。

ところがUnityでは1回の入力と連続的な入力とを分けて検出する仕組みが提供されているので、プログラマはそこを考慮せずに実装していくことができます。

マウスボタン : MouseButton

マウスの入力は"Input.GetMouseButtonメソッド"、"Input.GetMouseButtonDownメソッド"、"Input.GetMouseButtonUpメソッド"からそれぞれ取得することができます。もしも連続的に押されているかどうかを取得する必要があるのなら、"Input.GetMouseButtonメソッド"を利用します。

それぞれのメソッドの引数には対象とするマウスのボタン番号を与えますが、一般に、0が左、1が右、2がホイールボタンに対応付けられています。一方でDown,Upメソッドですが、こちらは一度の入力のみを検出します。つまり実行したゲームの更新時(≒Updateの呼び出しによるフレームの更新時)に1度だけtrueになり、次のゲームの更新時にマウスのボタンが変化していない(押されたまま、離されたまま)場合にはfalseとなります。

        //[1]ボタンが押されているかどうかを取得する
        bool mouseLeftButton = Input.GetMouseButton(0); 
        bool mouseRightButton = Input.GetMouseButton(1);
        bool mouseWheelButton = Input.GetMouseButton(2);

        //[2]ボタンが"1回"押されたかどうかを取得する
        bool mouseLeftButtonDown = Input.GetMouseButtonDown(0);
        bool mouseRightButtonDown = Input.GetMouseButtonDown(1);
        bool mouseWheelButtonDown = Input.GetMouseButtonDown(2);

        //[3]ボタンが"1回"離されたかどうかを取得する
        bool mouseLeftButtonUp = Input.GetMouseButtonUp(0);
        bool mouseRightButtonUp = Input.GetMouseButtonUp(1);
        bool mouseWheelButtonUp = Input.GetMouseButtonUp(2);

キーボード : Keyboard

キーボードの入力状態を取得する場合も、マウスの場合と同様に3種類のメソッドが用意されています。マウスの場合と同様に、GetKeyメソッドでは連続した入力を検出することができ、GetKeyDown,Upメソッドでは、更新時の1回の入力を検出することができます。このサンプルでは"Fキー"を対象にしています。

        //[4]キーボードの場合
        bool fKey = Input.GetKey(KeyCode.F);
        bool fKeyDown = Input.GetKeyDown(KeyCode.F);
        bool fKeyUp = Input.GetKeyUp(KeyCode.F);

用意されたボタン : GetButton

Unity(プロジェクト)では"標準的にあつかわれるボタン"というものが用意されています。要するに、特定のキーや特定のマウスボタンを、どちらも同じ動作としてあつかうことができるボタンです。

例えば"Fire1"というボタンが標準では登録されていますが、これはマウスの左ボタンもしくはキーボードの左Ctrlに対応付けられています。マウスの左ボタンを押しても、キーボードの左Ctrlを押しても、"Fire1ボタン"が押されたことになります。

プロジェクトで標準的に設定されたボタンを取得するには"Input.GetButtonメソッド"を利用します。引数には登録されたボタン名を与えます。またマウスやキーボードの入力と同じように、GetButtonDown,Upメソッドで1回の入力を検出することができます。

        //[5]プロジェクトに当てられた入力設定での取得する
        //マウスとキーボードの両方を同じボタンに当てることができる
        //キーボードでは、"Fire1=(Left)Ctrl", "Fire2=(Left)Alt", "(Left)Cmd"となっている
        bool fire1 = Input.GetButton("Fire1");
        bool fire2 = Input.GetButtonDown("Fire2");
        bool fire3 = Input.GetButtonUp("Fire3");

[補足1] 標準ボタンの設定

プロジェクトに用意された入力ボタンは(例えば)次の項目から設定・確認することができます。詳細についてはここでは割愛します。

  • メニューバー > Edit > Project Settings > Input

[補足2] ゲームを作ったことがない人へ必要性の解説

例えば、キーボードの入力"A"が"球の射出を実行する"としましょう。あるいはマウスの左ボタンとキーボードのAが同じ動作をするように実装するとします。もしも仕様変更や環境移植などで、キーボードが使えなくなったり、ボタンを変更する必要が出た場合はどうなるでしょうか。キーボードやマウスの入力と直接結びつけられた実装は、すべて実装先で再編集する必要が生じます。これは不用意なエラーを引き起こしかねませんし、繰り返し変更される場合、例えば操作感を確認しながら調整する場合などは大変不便です。しかしながら、キーボードの入力"A"を、プログラム内で入力"Fire"としておき、"Fire"を球の射出と結び付けておくとどうでしょうか。キーボードのAと"Fire"を結び付ける処理を書いた部分だけ変更すれば、それ以外の実装は変更する必要がありません。これがもしも1つや2つのボタンであれば直接実装しても良いかもしれませんが、5、10とボタンの数がある場合には、対応付けをまとめて管理しておいた方が、見通しも立ちますし、さらに不具合が起きる可能性を下げることができるのです。Unityではそのための機能が予め用意されているのです。

ホイールスクロール : MouseWheel(≒Scroll)

先の項目でマウスをあつかった際には、ホイールスクロールやその回転量についてあつかいませんでした。これは取得方法が異なるために、混乱しないようにと配慮したためです。マウスの座標についても取得方法がボタンなどとは異なるため、後に続いて解説します。

ホイールの回転を取得するには"Input.GetAxisメソッド"を利用します。引数は先に紹介したGetButtonと同様にプロジェクトに設定された既定の名前を指定します。ホイールの回転を取得するには、"Mouse ScrollWheel"を指定します。スクロールの値は手前に回す時にマイナスになり、奥に回す時にプラスになります。値はマウスやそのマウスの解像度によってことなりますが、普通は-0.1か0.1となり、回転させないときは0になります。高速ホイールマウスを利用したり素早く回転すると+-0.6位までの値は確認できました。

        //[6]マウスホイールの回転を取得する
        float mouseWheelScroll = Input.GetAxis("Mouse ScrollWheel");

マウスの座標 : MousePosition

マウスのスクリーン上の座標を取得するには、"Input.mousePositionプロパティ"を利用します。座標はレンダリングされた画面の左下を原点とし、右上に向かって伸びる座標系で取得されます。座標値は画面右上で最大となり、ピクセル(ドット)単位で与えられます。つまり1024*768解像度で実行される場合、右上の座標は(1024,768)となります。Unity開発環境でのGameViewで実行する場合と、ビルド後の実行ファイルで実行する場合とで値が変わらないように注意して実装する必要があるでしょう。また、Unityのレンダリング画面がいにマウスが位置する場合にも、レンダリング画面の左下を原点とする座標系での座標値が与えられる点にも注意します。つまりレンダリング画面の左にマウスが位置するとき、X座標はマイナスとなります。

        //[7]マウスの座標を取得する(左下が原点)
        Vector3 mousePosition = Input.mousePosition;

マウス座標の変位 : MouseX, MouseY

ゲームパッドのジョイスティックなどのように、徐々に傾いて行ったりする入力をマウスやキーボードで実現するには、前回更新時や、前回マウス座標取得時からの変位量を取得する必要があります。Unityではこれを標準的に取得する機能が提供されていて、先にマウスのスクロールを取得するために利用した"Input.GetAxisメソッド"を利用することで取得することができます。引数に与える取得対象の名前を、"Mouse X"ないし"Mouse Y"にすると、XとYの座標について、前回更新時からの移動量(変位)を取得することができます。つまりマウスをまったく動かしていなければ変位は0になります。

        //[8]入力の変位を取得する
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        //[9]Rawの試験(mouse)では効果が見られず
        float mouseXraw = Input.GetAxisRaw("Mouse X");
        float mouseYraw = Input.GetAxisRaw("Mouse Y");

また変位の取得については標準的にスムージング(データのノイズ、バラつきを消す)が施されていて、スムージングを施す前のデータは"Input.GetAxisRawメソッド"によって取得することができますが、マウスの変位を取得する分にはほとんど差が見られないことが多いようです。

(キー)入力の変位 : Horizontal, Vertical

ジョイパッド(スティック)の傾きの変化や、キーボードで徐々に入力の大きさを変更する、といった処理を実現する機能も、"Input.GetAxisメソッド"で実現することができます。引数に与える取得対象の名前を、"Horizontal"ないし"Vertical"を与えると、水平方向または垂直方向への入力の変位を取得することができます。こればかりは言葉で説明するのが難しいのでサンプルの値の変化を確認してもらうのが一番良いのですが、イメージ的には、キーボードでジョイパッドが実現できる、というイメージに近いです。

標準ではキーボードの上下左右キーないしWASDキーが対応していて、徐々に1ないし-1に値が近づき、キーを離すと徐々に値が0に近づいていきます。ジョイパッド(スティック)を限界まで倒した状態が1(-1)で、もとの位置にあるのが0、といったイメージです。

        //[10]入力の変位を取得する(Keyboard ver.)
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        //[11]Rawの試験(Smoothingされないので-1か1か0になる)
        float horizontalRaw = Input.GetAxisRaw("Horizontal");
        float verticalRaw = Input.GetAxisRaw("Vertical");

"Input.GetAxisRawメソッド"を利用すると、スムージング(値のバラつきを抑える処理)をかける前の値を取得することができますが、これは基本的にはジョイパッド(スティック)向けの機能です。キーボードの入力に適用すると、値が徐々に変化する、といったことはなくなり、0か1か-1の値のみ、つまり限界まで振り切った値のみを取得します。