[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(4)ラケットを動かす

#この解説は
Unityのサイトに昔からあるチュートリアルに、以下があります。
[「はじめてのUnity」(旧）
http://tutorial.unity3d.jp/archive/my-first-unity/](http://tutorial.unity3d.jp/archive/my-first-unity/)
これを独自にC#化したものをベースとしています。以下を
この解説は以下の段階があります、前の内容を実行した上でのものとして参照して下さい。現時点(20151026)では、[新しい「はじめてのUnity」の玉転がしゲーム](https://github.com/unity3d-jp/FirstTutorial/wiki)が公開されています。本サイトのブロック崩しと併せて学習すると広がりがあり、初期の学習にはとても有効です。

* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(1)ステージ配置](http://qiita.com/JunShimura/items/cbb0db8087a5cc75735e)
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(2)色を変える](http://qiita.com/JunShimura/items/1b2b4842e983022075de )
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(3)動くボール](http://qiita.com/JunShimura/items/dfb2bdbbc328869f62ec )
* [__[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(4)ラケットを動かす__]
(http://qiita.com/JunShimura/items/5fac20966bba6b223427)
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(5)消えるブロック](http://qiita.com/JunShimura/items/867179092a2a564bc88c)
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(6)ブロックを手作業で並べる](http://qiita.com/JunShimura/items/1f39e52414171c67bc71)


#プレイヤーが操作出来るラケットを作る
今回は、ゲームでよく使われる操作が出来るものを用意します。玉を打つので、ラケットとしましょう。

##ラケットを用意する
上に在るメニューの[GameObject]>[3D Object]>[Cube]を選んで下さい。
[![Gyazo](https://i.gyazo.com/a401d69d2a423a3aeae5e24ca6d826ac.gif)](https://gyazo.com/a401d69d2a423a3aeae5e24ca6d826ac)

これをラケットにします。Inspectorタブで、以下を変更します。

* 名前を分かりやすいように`racket`に
* `Transform`で`Position`を中央の手前に：例では(`0`,`0`,`-6`)
* `Transform`で`Scale`を横長に：例では(`3`,`1`,`1`)

[![Gyazo](https://i.gyazo.com/c251f0511db0a3201a5b789d93482cb1.png)](https://gyazo.com/c251f0511db0a3201a5b789d93482cb1)

##ラケットを操作可能にする
操作するには入力に関する設定と、入力に反応するScriptが必要になります。

###Inputのセッティングをする
メニューから[Edit]>[Project Settings]>[Input]を選びます。
ここで、キーの設定を変えたい場合は、必要に応じて変更しますが、今回はそのままにします。
ここのデータから読み込まれると思って下さい。
[![Gyazo](https://i.gyazo.com/7b2bc81e270492f49860b59482d8e7e9.png)](https://gyazo.com/7b2bc81e270492f49860b59482d8e7e9)

###`Racket`に`Rigidbody`コンポーネントを追加する
`Racket`オブジェクトを選択している状態で、メニューから、[Compornent]>[Physics]>[Rigidbody]を選びます。
[![Gyazo](https://i.gyazo.com/061c187abd567fa55103817365c95288.png)](https://gyazo.com/061c187abd567fa55103817365c95288)


|プロパティ|説明|今回の設定値|設定すると変化すること|
|:---------------|:-----------------------------|:----------|:----------|
|Mass|オブジェクトの質量 (単位 : kg)。|50|動き出す反応|
|Drag|空気抵抗。0 の場合、空気抵抗が 0|30|キーを離してから停止までの減速|
|Angular Drag|回転する際の空気抵抗。0 の場合、空気抵抗なし。|0|回転なし|
|Use Gravity|有効にすると、オブジェクトは重力の影響を受けます。|off|重力反応なし|
|Constraints/Freeze Position|座標の固定|yとzをon|横方向だけ移動|
|Constraints/Freeze Rotation|回転の固定|xとyとzをon|回転しない|

動作の反応を見て、`Mass`と`Drag`を調整します。


###`Racket`にScriptコンポーネントを追加する

`Racket`オブジェクトを選択している状態で、Inspectorタブの一番下にある[Add compornent]をクリックして、Scriptアセットを作成、追加します。ファイル形式はcsを選びます。
[![Gyazo](https://i.gyazo.com/0b5ea99bc34d45fb94a98079996fc882.gif)](https://gyazo.com/0b5ea99bc34d45fb94a98079996fc882)

Assetタブ内に、`Racket.cs`ができているのを確認します。
[![Gyazo](https://i.gyazo.com/7320b9c1c38d67bfcca14a3dbecea01a.png)]
(https://gyazo.com/7320b9c1c38d67bfcca14a3dbecea01a)

`Racket.cs`をダブルクリックし、`Input`によって力が加わるように変更します。

```csharp:Racket.cs
using UnityEngine;
using System.Collections;

public class Racket : MonoBehaviour {

    private float accel = 1000.0f;//加える力の大きさ
	
    // Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
        //力を加える
        this.GetComponent<Rigidbody>().AddForce(
            transform.right*Input.GetAxisRaw("Horizontal")*accel,
            ForceMode.Impulse);
	}
}
```

これで動くようになりました。Scriptを説明します。

|`code`|意味|今回の設定|
|:---|:---|:---|
|`private float accel = 1000.0f;`|加える力の大きさ|大きくすると動きが機敏になる|
|`Addforce`|力を加えるメソッド||
|`transform.right*Input.GetAxisRaw("Horizontal") * accel`|加える力の`Vector3D`|入力の左右×`accell`|
|`ForceMode.Impulse`|力の加え方|'Impulse'で瞬時に|

`transform.right`は単位ベクトルで、右方向を示します。これに、`Input.GetAxisRaw("Horizontal")`を乗算しています。`Input.GetAxisRaw("Horizontal")`の値は、`Vector3`型で返り、カーソルキーの押下状態で、右と左の向きを-1（左）,0（ニュートラル）,+1（右）返します。これ以外にキー押下だけでの判定で組み立てることも可能ですが、片側を押しながらもう一方を押すなど__同時押しの動作が簡単に出来る__ので、これを用いるのは有用です。

* `Input.GetAxisRaw`に関しては、以下を参考にして下さい。
 * [Unityスクリプトリファレンス Input.GetAxisRaw
http://docs.unity3d.com/ja/current/ScriptReference/Input.GetAxisRaw.html]
(http://docs.unity3d.com/ja/current/ScriptReference/Input.GetAxisRaw.html)

* `AddForce`に関しては、以下を参考にして下さい。
 * [Unityスクリプトリファレンス Addforce
http://docs.unity3d.com/jp/current/ScriptReference/Rigidbody.AddForce.html]
(http://docs.unity3d.com/jp/current/ScriptReference/Rigidbody.AddForce.html)
 * [Unity-スクリプトリファレンス　ForceMode
http://docs.unity3d.com/jp/current/ScriptReference/ForceMode.html]
(http://docs.unity3d.com/jp/current/ScriptReference/ForceMode.html)

##`Racket`の動作を調整する
上記でのパラメータは一例として設定していますが、機敏に動かしたい場合などは適宜、調整して下さい。

###動作の機敏さなどを変更する
以下を変えることで動作が変化します。

|変更対象|変更する部分|設定すると変化すること|
|:---------------|:-----------------------------|:----------|
|`Rigidbody`コンポーネント|`Mass`|動き出す反応|
|`Rigidbody`コンポーネント|`Drag`|キーを離してから停止までの減速|
|`Racket.cs`|`accel`|動く大きさ|

###ラケットの壁抜けの対応
`Rigidbody`コンポーネントの`Mass`を小さな値にすると、極端に速くなり壁を抜けてしまいます。こうした現象は、当たり判定によって変わります。画像を更新している時に当たり判定をしている状態がデフォルトで、「その瞬間に物体が重なり合ってるか」で判定します。この場合、物体の速度が速く、左右の`LeftWall`,`RightWall`の大きさを飛び越える速度で動くと、壁を抜けていきます。
これに対処するには、いくつか考え方があります。

#### 壁を抜けない状態でとどまるよう速度を考えて調整する
壁を抜けない程度に速度を抑える事で、当たり判定を変えないままでも可能になります。今の動き方では、端から端に移動し続けると最大速度になるので、それで抜けなければ問題ありません。

#### その他の方法（参考）
他には、こうした方法があります。

#####当たり判定を継続的に行い精度を高める
どちらを選択するかは考え方次第です。継続的に当たり判定するには、`Rigidbody`コンポーネントで、以下の設定を行います。これで壁は抜けませんが、少し処理が重くなります。
[![Gyazo](https://i.gyazo.com/7b6cc40c81ba2cf7df3d9545e1cbf260.png)](https://gyazo.com/7b6cc40c81ba2cf7df3d9545e1cbf260)

#####壁の大きさ、或いは当たり判定領域（`Collider`コンポーネント）を大きくする
速度よりも大きな幅を持った壁にする、あるいは`Collider`コンポーネントを大きくすると、当たり判定がおおきくなって抜けなくなる可能性が高まります。

#####壁を抜けない状態でとどまるよう矯正する
壁よりも外側に在る場合に内側の座標にx座標を強制的に戻す、最大速度を抑える等の方法があります。確実な方法になりますが、動作が物理的にならないので、ぎこちなくなる場合もあります。

###`Ball`の壁抜けの対応
`Racket`と`Ball`も衝突するので、`Ball`も考慮する必要があります。`Ball`の`Rigidbody`コンポーネントの`Collidion Detection`も、変更すると確実になります。


***
#まとめ

* プレイヤーが動かす物体は、`Input`から得られる情報で力を加えると、操作できる
* 当たり判定は、その瞬間だけで判定していると、速度が速い場合は抜けてしまう
* 当たり判定は継続的に判定も可能になるが、動作が重くなる場合もあるので注意する

***
この解説は以下の段階があります、前の内容を実行した上でのものとして参照して下さい。

* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(1)ステージ配置](http://qiita.com/JunShimura/items/cbb0db8087a5cc75735e)
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(2)色を変える](http://qiita.com/JunShimura/items/1b2b4842e983022075de )
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(3)動くボール](http://qiita.com/JunShimura/items/dfb2bdbbc328869f62ec )
* [__[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(4)ラケットを動かす__]
(http://qiita.com/JunShimura/items/5fac20966bba6b223427)
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(5)消えるブロック](http://qiita.com/JunShimura/items/867179092a2a564bc88c)
* [[超初心者向け]Unityチュートリアル「はじめてのUnity」のブロック崩しと同等をC#で::(6)ブロックを手作業で並べる](http://qiita.com/JunShimura/items/1f39e52414171c67bc71)