[Unity] ゲームパッドで視点操作とカメラ移動の同期１(FPS的操作)

#はじめに
\***注意**\*この記事はプログラミングの基礎知識がある前提で進みます。
レベルとしては**C++でちょっと書いたことあるよ**とか、**Javaならいじったことあるぜ**、って人ならば十分に理解できるでしょう。
あと**高校数学の知識**を必要とします。
#概要 
ARを始めたいと思い、Unityを始めたのはいいのですが、なんせコンシューマーゲーマーだったために、**WASD操作**に慣れていませんでした。
そこでPS3用に購入したHORIPADがあったので、**アナログスティック入力を導入する**ことにしました。
まだUnity歴1週間なので、へんてこプログラムにはご容赦ください。

学生が見ていたら言いたい、社会に出て数学は役に立たないかもしれないが、自分で何かを始めようとすると高確率で数学にぶつかるので、社会のレールにそって生きたいと思っている人以外は高校数学まではしっかり勉強しておきましょう。(今から使うからね～)

#環境設営編
早速**コントローラー設定**を済ませちゃいましょう。
実は左スティックの設定は既にされています。**さあUnityを開いてください。**

開いたら **Edit** -> **Project Setting** -> **Input** -> **Axes** の
**▼Horizontal** と **▼Vertical** がそうですので触らないでおきましょう。

次に **Size を 19** にしましょう。
そしたら**Cancelが2つできる**と思うので、以下の画像のように設定してください。
![input manager.JPG](https://qiita-image-store.s3.amazonaws.com/0/393071/bee83837-21b2-3e8d-3b4a-5f411e4bb0f5.jpeg)
これを完了させるともう入力が受け付けられるようになります。
**（自分でもあまり把握していないのですが環境において 3rd axis が 4th axis に、4th axis が 5th axis になる場合がありますので、動かしながら試してください。）**

さあ、簡単にUnityのフィールドを整えましょう。
適当な床とオブジェクトを配置します。

![fields.jpg](https://qiita-image-store.s3.amazonaws.com/0/393071/585693a6-6dfe-6918-ce5c-9c3109bd8eb4.jpeg)
こんな風に、上下左右に視点が動いているのを確認できるように大きめのオブジェクトを配置しておくといいでしょう。色も認識しやすい色にしておきましょう。
そしてヒエラルキーから **Main Camera** を選択し、**Inspector** の **Add Component** から検索窓に名前を入力
**Create and Add** を選択し、**C# スクリプト**を作成する。
歯車マークをクリックし、**Edit**を選択し**Visual Studio**が開かれる。**(今回は最後にしか使わないよ。)**


#視点操作編
さあ、カメラに動きをつけていきましょう。
今回使うキーワードはこちら

```C#:syntax
Input.GetAxis("Input_Name");  //戻り値　-1 ~ 1
Mathf.Sin(Radian);            //戻り値　-1 ~ 1 いわゆるSin関数ね
Mathf.Cos(Radian);            //戻り値　-1 ~ 1 いわゆるCos関数ね
Mathf.Deg2Rad                 //これを数値にかけると弧度法の値になる
transform.localRotation = Quaternion.Euler(x軸に対しどれだけ回転させるか, y軸に対しどれだけ回転させるか, z軸に対しどれだけ回転させるか);
                              //カメラの回転に使う
transform.Translate(x方向の移動量, y方向の移動量, z方向の移動量, 0.0F);
                              //カメラの移動に使う
```
**(0.0Fを入れとかないと正常に動作しない[誰か理由教えて！！])**

それでは初めにアナログスティックの入力を **Input.GetAxis("Input_Name");** で受け取ります。

```C#:Input
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
float angleH = Input.GetAxis("Horizontal2") * 5.0f;
float angleV = Input.GetAxis("Vertical2") * 5.0f;
```
こうするとしよう
**x** は**Horizontal(左スティック左右)**から**-1 から 1** までの値を受け取る。
**z** は**Vertical(左スティック上下)**から**-1 から 1** までの値を受け取る。
**angleH** は **Horizontal2(左スティック左右)**の**-1 から 1** の数値を**5倍に増幅**して受け取る。
**angleV** は **Vertical2(左スティック上下)**の**-1 から 1** の数値を**5倍に増幅**して受け取る。
**5倍に増幅している理由**はそのほうがスルスルと視点を動かすことができるからです。

これで変数としての受け取りを完了した。
####次に視界の左右について考えよう。
三次元空間内では周囲を見渡すには**360度**回ることができれば、すべてを把握できるだろう。
よって向く方向を **0 ～ 360度** で返す変数が必要だろう。
それじゃあこうすればいいのではないかとなる。

```C#:sight_x
float sight_x = 0;
void Update()
{
    sight_x = sight_x + angleH;
}
```
こうすることで左右に回転する変数ができた。
しかしずっと片方に回転を続けると **sight_x** が1000を超えたりする。
これでは後々コードを改変するときに大変なので、**0 ～ 360度** にするようにしよう。

```C#:sight_x+α
float sight_x = 0;
void Update()
{
    if (sight_x >= 360)    //sight_x が360度を超えると360を引く、超えた分の端数はsight_xに残る
    {
        sight_x = sight_x - 360;
    }
    else if (sight_x < 0)  //sight_x が0度を下回ると360からsight_xを引く、残った分はsight_xに残る
    {
        sight_x = 360 - sight_x;
    }
    sight_x = sight_x + angleH;
}
```
これで大丈夫、完成だ。
####次に視界の上下について考えよう。
これに関しては左右よりも簡単だ。
角度を制限してやるだけだ。
言葉にすると、
**sight_y** が **80 を超えると**、**0を超える数値を受け付けないよう**にし、そして
**sight_y** が **-90 を下回ると**、**0 未満の数値を受け付けないよう**にする。つまりこう

```C#:sight_y
float sight_y = 0;
void Update(){
    if (sight_y > 80){
        if (angleV < 0){
            sight_y = sight_y + angleV;
        }
    }
    else if (sight_y < -90){
        if (angleV > 0){
            sight_y = sight_y + angleV;
        }
    }else{
        sight_y = sight_y + angleV;
    }
}
```
そこに **transform.localRotation = Quaternion.Euler();**をつけて入力を受け付ける。
そして**sight_xとsight_y**をまとめるとこうなる

```C#:sight
// このコードをVisual Studioに写して、プレイボタンを押し、実行したら右スティックで視点が動きます。

float sight_x = 0;
float sight_y = 0;

void Update()
{
    float angleH = Input.GetAxis("Horizontal2") * 5.0f;
    float angleV = Input.GetAxis("Vertical2") * 5.0f;

    if (sight_y > 80){
        if (angleV < 0){
            sight_y = sight_y + angleV;
        }
    }
    else if (sight_y < -90){
        if (angleV > 0){
            sight_y = sight_y + angleV;
        }
    }else{
        sight_y = sight_y + angleV;
    }

    if (sight_x >= 360)    //sight_x が360度を超えると360を引く、超えた分の端数はsight_xに残る
    {
        sight_x = sight_x - 360;
    }
    else if (sight_x < 0)  //sight_x が0度を下回ると360からsight_xを引く、残った分はsight_xに残る
    {
        sight_x = 360 - sight_x;
    }
    sight_x = sight_x + angleH;
    transform.localRotation = Quaternion.Euler(sight_y, sight_x, 0);
}
```

**sight_y と sight_x** が逆に感じるかもしれませんが、**x軸に対して回転**なので**sight_y**でいいのです。

次にカメラを移動させよう。

```C#:move
void update(){
    float dx = Input.GetAxis("Horizontal");
    float dz = Input.GetAxis("Vertical");

    transform.Translate(dx, 0, dz, 0.0F);
}
```

はい、できた！！！.....        　　　　　　　そうはいきません。

何故でしょう、実際に実行して確認してみてください。
どうすればいいかは、次回に回したいと思います。

続編ができました　→　https://qiita.com/Vonlet/items/665da51d483229c4ad24

ふう、つかれた