InputクラスのGetKey系とGetButton系のどっちを使えば良いの？を調べてみた

# はじめに

　Inputクラスには、キーやボタンを押したことを検知するメソッドがいくつかあります。例えば、次のようなメソッドがありますね。

* [Input.GetKeyDown](http://docs.unity3d.com/ScriptReference/Input.GetKeyDown.html)
* [Input.GetKey](http://docs.unity3d.com/ScriptReference/Input.GetKey.html)
* [Input.GetKeyUp](http://docs.unity3d.com/ScriptReference/Input.GetKeyUp.html)
* [Input.GetButtonDown](http://docs.unity3d.com/ScriptReference/Input.GetButtonDown.html)
* [Input.GetButton](http://docs.unity3d.com/ScriptReference/Input.GetButton.html)
* [Input.GetButtonUp](http://docs.unity3d.com/ScriptReference/Input.GetButtonUp.html)

 
　GetKey系はそれぞれのメソッドで二つのオーバーロードがあります。一つは、それぞれのキーを表すKeyCode列挙型を引数にとるもの。もう一つは、キーの文字列string型を引数にとるものです。

　一方で、GetButton系はstring型を引数にとるものしかありません。

　ここで一つ疑問が出てきます。GetKey系にもGetButton系にもstring型を引数にとるメソッドがありますが、これはどちらを使えば良いのでしょうか。結局同じなのでしょうか？

　結論から言うと、使い方も使いどころももちろん違います。今回はそれをまとめてみました。

　ちなみにGetKeyDown、GetKey、GetKeyUpがどのタイミングでtrueを返すのか、それぞれの状態がどのように遷移するのかを[こちら](http://qiita.com/RyotaMurohoshi/items/a5cde3c17831adda12db)の記事にまとめました。

# それぞれのメソッドの整理

　今回はInput.GetKeyDownメソッドとInput.GetButtonDownメソッドと、その関係を例に上げて紹介していきます。
## Input.GetKeyDown(string name)メソッド

　　[Input.GetKeyDown(string name)](http://docs.unity3d.com/ScriptReference/Input.GetKeyDown.html)は、押したことを検知したいキーの文字列を引数に渡します。スペースキーであれば`"space"`、右の矢印であれば`"right"`などの文字列です。[こちら](http://docs.unity3d.com/Manual/ConventionalGameInput.html)のConventional Game InputというページのButton Namesという節にそれぞれキーがどの文字に対応しているかが載っています。

　このメソッドには良くない点があります。Spaceキーを検知するには、文字列として、`"space"`を渡す必要があります。`"Space"`ではダメです。このように、大文字小文字まで[こちら](http://docs.unity3d.com/Manual/ConventionalGameInput.html)に載っているボタンの名前で扱う必要があります。また、文字列ですのでタイポしてしまう可能性もあります。

　ちなみに対応していない文字列を渡した場合、次のような実行時例外が発生します。

```csharp:不正な文字列を渡した場合の実行時例外
UnityException: Input Key named: Space is unknown
UnityEngine.Input.GetKeyDown (System.String name)
InputGetKey.Update () (at Assets/InputGetKey.cs:8)
```

　後述するInput.GetKeyDown(KeyCode key)メソッドかInput.GetButtonDown(string buttonName)メソッドを使った方がいいです。

## Input.GetKeyDown(KeyCode key)メソッド

　[KeyCode列挙型](http://docs.unity3d.com/ScriptReference/KeyCode.html)というのがあります。それぞれの要素が、一つ一つのKeyを表します。例えば、[KeyCode.Space](http://docs.unity3d.com/ScriptReference/KeyCode.Space.html)や[KeyCode. UpArrow](http://docs.unity3d.com/ScriptReference/KeyCode.UpArrow.html)などがあり、他にもたくさんの要素があります。

　[Input.GetKeyDown(KeyCode key)](http://docs.unity3d.com/ScriptReference/Input.GetKeyDown.html)は、KeyCode列挙型を引数に取ります。

　KeyCodeまでタイプすれば、扱えるものが列挙されるのも便利ですし、文字列を引数に取るものと違い、タイポする心配もありませんね。string型を引数にとるメソッドの欠点は、こちらを使えば解決ですね。

　ちなみに後述する、Input.GetButtonDown(string buttonName)メソッドを使った方がいい場合もあります。

## Input.GetButtonDown(string buttonName)メソッド
　最初に紹介した、Input.GetKeyDown(string name)と同じように[Input.GetButtonDown(string buttonName)](http://docs.unity3d.com/ScriptReference/Input.GetButtonDown.html)も文字列型を引数に取ります。

　Input.GetButtonDown(string buttonName)も、Input.GetKeyDown(string name)と同じように[こちら](http://docs.unity3d.com/Manual/ConventionalGameInput.html)にのっている`"space"`や`"right"`などの文字列を渡せばいいのでしょうか。実はそうではありません。Input.GetButtonDownなどInput.GetButton系のメソッドが引数にとる文字列は、Input系の設定が関係します。


　GetButtonDownなどのGetButton系のメソッドは、次のように使うと思います。

```csharp:Input.GetButtonDownのサンプル
using UnityEngine;

public class InputGetKey : MonoBehaviour
{
	void Update ()
	{
		if (Input.GetButtonDown ("Jump")) {
			Debug.Log ("Input.GetButtonDown Jump");
		}
	}
}
```

　ここで使っている、文字列`"Jump"`という文字列はどこで設定されているのでしょうか。

　メニューの、Edit->ProjectSettings->Inputとたどると、Inspectorビューに、次の画像のようにInputManagerが表示されます。

![img1.png](https://qiita-image-store.s3.amazonaws.com/0/4125/e0104421-7f28-4cb9-76c2-bbb83d9b6466.png "img1.png")


　このInspectorビューの`Axes`を開くとデフォルトでは次のように15個の項目表示されます。(Unity4.5.2で確認)

![img2.png](https://qiita-image-store.s3.amazonaws.com/0/4125/b20603e4-c533-5a17-ba1c-dd1b3d6b4ce0.png "img2.png")


　上記画像2中の6個目のJump(一番したのではなく)を開いてください。

![img3.png](https://qiita-image-store.s3.amazonaws.com/0/4125/da6d13f5-d568-1367-50e6-5a7922ee3f9a.png "img3.png")


　開くと上の画像のようにいくつか項目が表示されると思います。

　ここではNameという項目とPositive Buttonという項目、そしてTypeという項目に注目してください。Nameは`"Jump"`となっていて、Positive Buttonは`"space"`に、項目は`Key or Mouse Button`になっていますね。これはつまり、Spaceボタンを押したかどうかを、Input.GetButtonDownなどのGetButton系のメソッドに`"Jump"`という文字列を引数を渡すことで、検知することができるということです。

　Input.GetButton系のメソッドでは、Axesの各項目のNameで設定した文字列を引数に取ることが可能です。次の4個の項目で設定したボタンと紐づいています。

* Positive Button
* Negative Button
* Alt Positive Button
* Alt Negative Button

　Jumpでは、Positive Buttonしか設定されていませんが、複数のボタンを一つの文字列に設定することが可能ですね。また、設定するボタンの文字列は[こちら](http://docs.unity3d.com/Manual/ConventionalGameInput.html)のものを使います。

　PositiveとNegativeがあるのは、[Input.GetAxis](http://docs.unity3d.com/ScriptReference/Input.GetAxis.html)や[Input.GetAxisRaw](http://docs.unity3d.com/ScriptReference/Input.GetAxisRaw.html)で正方向・負方向の入力を検知するためです。もし任意のボタンを用いる入力に対して複数のボタンを割当るならば、`Positive Button`と`Alt Positive Button`のみを使った方がいいと思います。

　さて、結局GetButtonDownなどGetButton系のメソッドは結局どんな文字列引数に渡せば良いのか。それは、InputManagerのAxesの項目で設定してあるものを渡せば良いのです。デフォルトでは、`"Jump"`や`"Fire1"`などが渡せる文字列ですね。

　設定されていない項目を引数に渡すと、次のような実行時例外が発生します。

```csharp:GetButton系に不正な文字列を渡した場合の実行時例外
UnityException: Input Button NotSet is not setup.
 To change the input settings use: Edit -> Project Settings -> Input
InputGetKey.Update () (at Assets/InputGetKey.cs:8)
```

　ちなみに文字列を引数にとるので、タイポには気をつける必要がありますね。

# Input.ManagerとInput.GetButton系のメソッドをもうちょっと

　Input.Managerの設定は、`ProjectSettings/InputManager.asset`に保存されています。Editorの保存を`Force Text`にした場合、`ProjectSettings/InputManager.asset`は、YAMLファイルとして読むことが可能です。

　さてデフォルトでは、`"Jump"`、`"Fire1"`などが、設定されていると述べましたが、これらも`ProjectSettings/InputManager.asset`に設定が保存されています。

　実は、デフォルトの設定は全て削除することもできます。画像の用に`Axes`の`Size`を0にした場合、全ての設定が削除されます。

![img4.png](https://qiita-image-store.s3.amazonaws.com/0/4125/9f046977-6cce-9278-dff2-ffe9f1ceaff0.png "img4.png")

　このように全ての項目を削除した場合、次のコードは実行時例外になってしまいます。

```csharp:
using UnityEngine;

public class InputGetKey : MonoBehaviour
{
	void Update ()
	{
		if (Input.GetButtonDown ("Jump")) {
			Debug.Log ("Input.GetButtonDown with Jump");
		}
	}
}
```

エラーログは次のような感じですね。

```
UnityException: Input Button Jump is not setup.
 To change the input settings use: Edit -> Project Settings -> Input
InputGetKey.Update () (at Assets/InputGetKey.cs:8)
```

　Axesには自由に項目を追加できます。`"Smash"`を追加してみましょう。キーは、SpaceキーとReturnキーを割り当ててみます。まず、Axesのサイズを1にします。そして次の画像のように項目を設定します。

![img5.png](https://qiita-image-store.s3.amazonaws.com/0/4125/23679f4a-3eab-37b0-25cb-8d67853b3031.png "img5.png")


　次のコードを実行し、SpceキーやReturnキーを押すとログが出力できます。

```csharp:
using UnityEngine;

public class InputGetKey : MonoBehaviour
{
	void Update ()
	{
		if (Input.GetButtonDown ("Smash")) {
			Debug.Log ("Input.GetButtonDown with Smash");
		}
	}
}
```

　簡単に項目を設定することが可能ですね。

　さて、PC スタンドアローンでゲームをビルドしてみましょう。ビルドし実行すると、設定ダイアログが出てくると思います。デフォルトではGraphicsタブですが、これをInputタグに切り替えてみます。

![img6.png](https://qiita-image-store.s3.amazonaws.com/0/4125/db2c6168-77f2-a9eb-c3a1-4abdf8f3f257.png "img6.png")

　Input.Managerでの項目が表示されています。今、デフォルトは全て削除して`"Smash"`という項目を設定しているので、上のような画像になると思います。画像中に"Double-click an entry to change it."とありますね。このメッセージの通り、PC スタンドアローンの場合、起動時にユーザーがキーの割当を設定することが可能なのです。

# で、結局何を使えば良いの？

　本番環境では使わないけれど、デバック時にちょっと確認したいコードなどでは、KeyCode列挙型を引数にとるInput.GetKey系のメソッドを使った方がいいと思います。タイポすることがありませんし。

　本番環境でも使うコードでは、Input.GetButton系を使った方がいいと思います。PCのスタンドアローンの場合、ユーザーがキーの割当設定を自分で上書きできるからです。

# まとめ

　この投稿では、Input.GetKey系の引数がstringのオーバーロード、KeyCode列挙型を引数にとるオーバーロード、Input.GetButton系のメソッドの違いについてまとめました。

　この投稿では、Input.GetKeyDownとInput.GetButtonDownを中心に説明しましたが、これはInput.GetKeyとInput.GetButton、そしてInput.GetKeyUpとInput.GetButtonUpもあてはまります。

　サンプルコードなどで、何気なく使われることが多いメソッドですが、しっかりと適切なものを使い分けたいですね。

# あわせて良かったらどうぞ！

* [GetKeyDownとかGetButtonUpとかがtrueになるタイミングの遷移について](http://qiita.com/RyotaMurohoshi/items/a5cde3c17831adda12db)
* [Input.GetAxisとInputManagerの関連設定について](http://qiita.com/RyotaMurohoshi/items/7868752a3f056affa2df)