Unityでコインプッシャー


モトネタ
 http://www.nicovideo.jp/watch/sm12948504
RadiumSoftware さんに感謝！

環境
 Unity 4.6.2f1

### 新規プロジェクト作成
Unity [File]-[New Project]

### コイン作る

- [GameObject]-[3D Object]-[Cylinder]
- 名前はCoinに

サイズ変更する

- InspectorのTransform-scaleでサイズ変更 Yを0.1に

物理挙動を与える

- コインオブジェクトを選んで、[Component]-[Physics]-[RigidBody]

実行すると落ちるコインになる。

デフォルトのカプセルコライダーだと当たり判定が球状なので、コインが浮いてしまう。

- Capsule Coliderはremove Compornentで削除
- [Component]-[Physics]-[Mesh Collider]を追加
- 処理が重いのでConvexチェックボックスをON

動きを派手にしたい。コインっぽくしたい。

- [Assets] - [Create] - [Physics Material]
- 名前はcoin
- 摩擦係数(Dynamic Friction) は低め 0.4->0.2
- 反射係数(Bounciness) は高め 0 -> 0.6
- D&Dでコインオブジェクトに与える。

コインっぽい色に

- [Assets] - [Create] - [Material]
- 名前はcoin
- Shader は　specular でテカテカさせる。
- MainColorは金色
- Shinness は最大（くらい）
- D&Dでコインオブジェクトに与える。

### 明かり作る

- [GameObject]-[Light]-[Directional light]
- 適当に位置移動

### 床作る

- [GameObject]-[3D Object]-[Cube]
- Position は全部0
- Scale は10,1,10

### カメラの位置調整

- すでにあるMainCameraを動かす
- オブジェクトの動かし方は http://ws.cis.sojo-u.ac.jp/~izumi/Unity_Documentation_jp/Documentation/Manual/Learning%20the%20Interface.html 参照

### コインを生成出来るようにする。

大量生産するものはプレハブに格納するのがよい。

- [Assets] - [Create] - [prefab]
- 名前は coinPrefab
- コインオブジェクトをD&D
- コインオブジェクトは消す。

実際にコインを生み出すオブジェクトを作る。

- [GameObject] - [create Empty]
- 名前は spawner

オブジェクトの挙動をスクリプトで制御する。

- [Assets] - [Create] - [JavaScript]
- 名前は spawner
- D&Dでspawnerオブジェクトに食わせる。

``` spawner
#pragma strict

var prefab : Transform;
function Update () {
		if (Input.GetButtonDown ("Fire1")) {
			Instantiate (prefab, transform.position, transform.rotation);
		}
}
```

`var prefab : Transform` を宣言することで、spawnerオブジェクトのInspectorにPrefab変数が露出する。
ここに、coinPrefabをD&Dする。

実行すると、マウスクリックでコインが生成されるようになる。
生成場所が変わらないので、positionに変化を付けて左右に散らすようにする。

``` spawner
#pragma strict

var prefab : Transform;
function Update () {
		if (Input.GetButtonDown ("Fire1")) {
			var offs = Vector3(Mathf.Sin(Time.time * 7), 0, 0);
			Instantiate (prefab, transform.position + offs , transform.rotation);
		}
}
```

### プッシャーを作る

- 床部分のcubeををDuplicateで、プッシャーと引掛け台を作る。
- プッシャーはコインと物理干渉をするはず。
- - [Compornent]-[Physics]-[rigidbody]にする。
- プッシャーはスクリプトで制御するので`is kinematic`にチェックする。

``` pusher
#pragma strict

var origin : Vector3;
function Awake () {
	origin = rigidbody.position;
}

function Update () {
	var offs = Vector3(0, 0, Mathf.Sin(Time.time));
	rigidbody.MovePosition(origin +  offs);
}
```

- Awake は起動時に一度だけ呼ばれる。
- 起動時の初期位置をoriginに保存しておき、そこからの差分としてoffsetを加算する。

### おちたコインの制御

落ちたコインを消すための空オブジェクトを作る。

- [Game Object]-[Create Empty]
- 名前はremover
- 台の下に50x50ぐらいの大きさで置いておく。
- コインとの当り判定が必要。
- [Component]-[Physics]-[Box Collider]
- あたった時の処理がいるので `is Trigger`チェックをつける。

削除処理のスクリプトを記載し、removerにD&D

- [Assets]-[Create]-[JavaScript]
- OnTriggerEnterメソッドで、引数のゲームオブジェクトを削除。

```remover
#pragma strict

function OnTriggerEnter (other : Collider) {
		Destroy(other.gameObject);
}
```

http://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html

あたった時はポイントを加算するようにする。
そのためにポイントを保持するオブジェクトを作る。

- [GameObject] - [Create Empty]
- 名前はscore
- 表示も出来るようにGuiTextコンポーネントを付与する。
- [Component]-[Rendering]-[GUITEXT]
- 同名のスクリプトも用意してD&Dする。


```score
#pragma strict

static var score : int;

function Awake() {
	score = 30;
}

function Update() {
	guiText.text = score.ToString();
}
 
```

起動時にscoreを30で初期化し、guiTextに表示する。

当り判定の床も作る。
リムーバーオブジェクトをコピペ。
スクリプトもほぼ同様だが、scoreを加算する処理だけ追加。

``` remover2
#pragma strict

function OnTriggerEnter (other : Collider) {
		Destroy(other.gameObject);
		score.score += 3;
}
```

生成時にポイントを減算する。spawnerを下記のように変更

```spawner
#pragma strict

var prefab : Transform;
function Update () {
		if (Input.GetButtonDown ("Fire1")) {
			var offs = Vector3(Mathf.Sin(Time.time * 7), 0, 0);
			Instantiate (prefab, transform.position + offs , transform.rotation);
			score.score -=1;
		}
}
```


### Androidで動かしたい。

iOSで動かそうとするとカネかかるのでAndroidで動かす。
最新のJDKをインストールする。macに入っているjavaは1.6なので古すぎる。

http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

ADKをインストールする。
よくわからないのでIDE(Android Studio)ごとインストール。
起動後、SDKマネージャを開くと、~/Library/Android/sdk にADKがインストールされている模様。

端末側の設定で、Androidの「開発者向けオプション」を有効化、「USBデバッグ」のチェックを付けておく。

unityにて

[Edit]-[Project Settings]-[Player]を開く。
OthersSettingのBundle Identiferがそのままだと怒られるので適当に変える。

[File]-[Build Settings]
PlatformをAndroidに変更してBuild and Run


-----
よくわからなかったとこ。

# GameObject/Component/Assets
## GameObject

http://docs.unity3d.com/ja/current/Manual/GameObjects.html

- Unityの世界にある全てのモノがGameObject
- ただしGameObject自身にはなんの特性もない。
- 様々な特性を追加できるハコと考えると良さそう。

## Component

http://docs.unity3d.com/ja/current/Manual/UsingComponents.html

- GameObjectに設定する様々な特性がComponent
- GameObjectに複数のComponentを設定することで、GameObject自体の特性・振る舞いをコントロールすることができる。
- すべてのGameObjectはデフォルトでTransform コンポーネントが付いている。
- これは、位置・回転・大きさを定義するためのコンポーネント。

## Assets
よくわからん・・・。こんな感じ？

- ComponentとしてGameObjectに設定されうるあらゆる素材。
- 素材のままではUnityの世界には存在してない。
- たとえば、scriptも作成しただけではタダの素材。
- CompornentとしてGameObjectに設定することで利用できる。

# いろんなComponent

## rigidbody

- GameObjectに（現実世界同様の）物理特性を与えるコンポーネント
- Mass:質量[kg]
- Is Kinematic : GameObjectが物理特性で動かなくなる。プッシャーにこのフラグをつけたのは、物理特性で勝手に挙動するのを防ぐため。プッシャーはスクリプトで計算した位置情報でのみ挙動させたかった。

## Collider

- GameObject同士の衝突を制御するコンポーネント
- GameObjectの形に応じて様々な種類が存在する。
- Mesh Colliderのconvexフラグをつけると、オブジェクトの凸部分に応じた衝突判定ができる。
-  Convex なしだと重い（コライダーが複雑になるから？）
-  convex なしだと他のMesh Collderとの衝突判定ができない。（処理が複雑すぎるから？）

http://appdeappuappu.hateblo.jp/entry/2014/06/02/082538
http://octagonalroom.blogspot.jp/2011/08/unity9.html

## Mesh / Material

http://docs.unity3d.com/ja/current/Manual/comp-MeshGroup.html

- GameObjectの見た目。モデリングを定義するのがMesh
- Materialは Meshの質感を定義するコンポーネント

## prefab

- GameObject を生成するためのAssets
- GameObjectを生成するハコのようなイメージだったが、GameObjectの雛形と思ったほうが良さそう。
- prefabに与えた変更は、そこから生成される全てのObjectに影響を与える。