【Unity(C#)】キーボードの同時入力を禁止する

##UnityのInput(キーボード入力)は同時入力できてしまう
`Input.GetKeyDown`を例に話を進めていきます。
[こちらの記事](https://qiita.com/RyotaMurohoshi/items/a5cde3c17831adda12db)にもありますように、
指定したキーを押した瞬間、1フレームだけ呼び出されてtrueを返します。

もし同時に押したらどうなるのか検証してみました。

```C#
void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            print("A");
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            print("S");
        }
    }
```
![Key同時押し.png](https://qiita-image-store.s3.amazonaws.com/0/244071/2eba7347-17f3-47e6-67c0-cb0e09ecf0c7.png)


このように両方が同じように増えました。
キー入力は人間の手で行っているので
厳密に同時(同一フレーム上)に増えているかどうかは読み取れませんが、
[前回の記事](https://qiita.com/OKsaiyowa/items/2c5bdecc1edb5eea6eb0)で発生したバグは
**同一フレーム上でキー入力を受け取ってしまったこと**が原因かと思われます。

![Bag.png](https://qiita-image-store.s3.amazonaws.com/0/244071/ec651ae8-fbcc-eab9-5e97-2ef83a278de6.png)

**矢印キーの入力が同時に行われてしまったこと**でこのようなバグが発生しています。
※正しい挙動は前回の記事を参照ください


##同時(同一フレーム)入力できるのはヤバい
ヤバいです。
例えば、自動販売機。
ふざけてボタンを同時押ししたことがあるかと思います。(ない？)

あれがもし奇跡的なタイミングで両方のボタンをぴったり同時に押した場合、
反応してしまう仕組みだったとしたらどうでしょうか。
一本タダで手に入ってしまいます。それくらいヤバいです。

とてもわかり易い例えは置いといて、
同時押しを想定していないのであれば、バグの温床になりかねません。

なので、キーボードは片方づつ押せるようになっていてほしいものです。

##namespaceを使ってみた
namespaceは`コンポーネントをいっぱい登録して簡単にどこでも呼び出しやすくしました`
みたいな理解をしています。(合ってますか？)

[Unityのスクリプトリファレンス](https://docs.unity3d.com/ja/current/Manual/Namespaces.html)には
大規模な開発にもってこいです みたいなことが書いてありました。
(それ以外に使う理由ってありますか？よく使う方見てたらコメントください)

現時点であまり縁がないですが使ってみようと思います。


```C#
using UnityEngine;

namespace InputKey{
    /// <summary>
    /// 同時入力を禁止する
    /// </summary>
    public static class MyInput 
    {
        static bool isCheck_Input;

       public static bool MyInputKeyDown(KeyCode key)
        {
            if(Input.anyKeyDown == false) isCheck_Input = false;
         
            if (isCheck_Input==false)
            {
                if (Input.GetKeyDown(key))
                {
                    isCheck_Input = true;
                    return true;
                }
            }
            return false;
        }
    }
}
```

このスクリプトは何にもAdd Componentしなくていいやつっぽい(staticなので)です。

次は使う側です。`using InputKey`を名前空間に追加します。

```C#
using UnityEngine;
using InputKey;

public class Test : MonoBehaviour
{
    void Update()
    {
        if (MyInput.MyInputKeyDown(KeyCode.A))
        {
            print("A");
        }

        if (MyInput.MyInputKeyDown(KeyCode.S))
        {
            print("S");
        }
    }
}
```

これで同時入力(同一フレーム入力)できなくなってました:ok_hand:


```C#
void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            print("A");
        }
        else if (Input.GetKeyDown(KeyCode.S))
        {
            print("S");
        }
    }
```
`else if`使えば同一フレームを回避できるらしいです！
ただ、１フレームずれただけだと見た目ではあまり変化ないです。


##もっと厳格な同時押し禁止
`MyInputKeyDown`にしろ、`else if`にしろ、
同時入力が避けられるのは1フレームのみです。

**キーを押し込んでいる間は他のキーを押せない状態**こそ
**真の同時押し禁止**といえるでしょう。

```C#
 //真の同時押し不可
        public static bool MyInputKey(KeyCode key)
        {
            if(Input.anyKey == false) isCheck_Input = false;
         
            if (isCheck_Input==false)
            {
                if (Input.GetKey(key))
                {
                    isCheck_Input = true;
                    return true;
                }
            }
            return false;
        }
```
これで
**押しっぱなしでも一回しか反応しない、かつキーを押し込んでいる間は他のキーを押せない状態**になりました。

これが真の同時押し禁止だーーー！

---
2019/03/28 追記

namespaceを使う理由を教えてもらいました！
**プロジェクトを外部に公開したり、配布したりする際**にも使えるそうです。

例えば、
**importしたscriptに記述されたクラス名が自分のプロジェクト内のscriptに記述されたクラス名と一致**した場合、
エラーとなってしまいます。
そういった**汎用的なクラス名の衝突を避ける目的**で利用されるそうです！

アセットなどによくnamespaceが使われている理由もそのためらしいです。

---
2019/10/07 追記　

これほんとに同時入力禁止なのか？って思ったのでもっかい調べてみました。
というかそもそも、同時に別のキー入力の受付ってできるのか？と思って調べてみました。

通常のInputだと 同時に別のキー入力できてました。
![SameTimeInput.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/09d44d09-4680-cd13-6351-ac83549a10c6.png)

で、この記事のMyInputとかいうダサい名前のクラス使ったらできなくなってました。
やるじゃん過去の俺。