C#Unity基本備忘録

# Unity備忘録
自分用とサークル用の備忘録として残します。（ミスがあるかも）
## StartとUpdate
### void Start()
Startに書かれた処理が**始めに1度だけ**実行されます。

```c#
void Start(){
    /*ここに処理を書く*/
}
```
シーンが始まった時に**変数を初期化**したり、他のゲームオブジェクトやスクリプトを**キャッシュ（＝参照を取得して変数）に入れておくこと**したりするときに活躍します。

```c#
void Start(){
    //コンソールに文字を表示
    Debug.Log("Startに書かれてるよ");
}
```
このようにStartメソッドに記入すると、実行した際1度だけ表示されます。
![](https://i.imgur.com/zM7SsK5.gif)

### void Update()
Updateに書かれた処理が**1秒間に60回**実行されます。

```c#
void Update(){
    /*ここに処理を書く*/
}
```

頻繁に呼び出されるため、重い処理はなるべく行わないようにする必要があります。

```c#
void Update(){
    Debug.Log("Updateに書かれてるよ");
}
```
このようにStartメソッドに記入すると、実行している間ずっと表示されます。また、例えば「右に３マス進む」という処理を書くと、１秒後には180マス（60回×3マス）進むことになります。

## コンポーネント

### GetComponent<>()
これは、1回だけ呼び出せばいいため、Startメソッドに記載する。
**物体に追加したコンポーネント（物理特性を制御できるRigidbodyなど）をプログラミングから使えるようにする**メソッドです。

```c#
型 変数名;
void Start(){
    //「<>」の中は、左辺と統一しなければならない
    変数名 = GetComponent<型>();
}
```

「<>」の中は、左辺と統一しなければならない。例えば、物理特性ををプログラムで制御したい場合、

```c#
Rigidbody rb = GetComponent<Rigidbody>();
```
となる。

### GetComponents<>()
物体に**複数**追加したコンポーネントをプログラミングから使えるようにするメソッドです。

```c#
AudioSource[] audios;//配列(おもちゃ箱)を用意
void Start(){
    //「<>」の中は、左辺と統一しなければならない
    audios = GetComponents<AudioSource>();
}
```
これは、Unityで音楽を制御する際に使用する例になります。もちろん、AudioSourceという部分をGameObjectと変更すれば、いっぺんに複数のゲームオブジェクトを制御することができます。

## 当たり判定
当たり判定とは、「物体と物体がぶつかったことを知る判定」のことを言います。イメージ的には、座標Aと座標Bが重なっているかどうかの判定するようなイメージです。

当たり判定をしようするためには、オブジェクトにRigidbody（物理特性）とCollider（オブジェクトの形状を定義）をつける必要があります。

当たったオブジェクトの情報を得たい場合は、引数から参照できます。

### OnTrigger
- **当たり判定が作動した時に呼ばれる処理**

```c#
void OnTriggerEnter(Collider col){
    Debug.Log("すり抜けじゃあ！！！");
}
```
物体をすり抜けさせるためにColliderの「is Trigger」にチェックを入れることを忘れずにしましょう。
![](https://i.imgur.com/X9aYsMD.gif)

- **物体がすり抜けている間に呼ばれ続ける処理**

```c#
void OnTriggerStay(Collider col){
    Debug.Log("当たってる");
}
```
![](https://i.imgur.com/4uYIqfj.gif)

- **物体が通り抜け終わったに呼ばれる処理**

```c#
void OnTriggerExit(Collider col){
    Debug.Log("通り抜け終わった");
}
```
![](https://i.imgur.com/7YDKoZo.gif)

### OnCollision
- **物体同士がぶつかった時に呼ばれる処理**

```c#
void OnCollisionEnter(Collision col){
        Debug.Log("当たった!");
}
```
![](https://i.imgur.com/zqyIeRb.gif)

- **当たっている間に呼ばれ続ける処理**

```c#
void OnCollisionStay(Collision col){
    Debug.Log("当たっているぞぉ");
}
```
![](https://i.imgur.com/ygqLZtU.gif)

- **当たっていた物体が離れたときに呼ばれる処理**

```c#
void OnCollisionExit(Collision col){
    Debug.Log("離れた！！！");
}
```
![](https://i.imgur.com/dh0f4vR.gif)

- **体同士が当たった時の処理が「Collider」**
- **物体がすり抜けた時の処理が「Trigger」**

## 生成と破壊
### ゲーム内に物体を生成
例えば、ボタンを押した際に弾が生成され、発射するゲームを作成するとなった場合、弾の生成がInstantiate関数を使用します。

```c#
//Instantiate(生成したい物, 生成する座標, 回転)
Instantiate(gameobject,Vector3,Quatanion);
```

もし下記のように記載した場合、gameobjectと同じものが(0,0,0)の位置に生成されます。(球体をgameobjectに設定していたら球体と全く同じものが生成される、実際にやったものを見せると良い)
```c#
/*
 * Vector3->3次元+.zero->0の位置=(0,0,0)
 * Quatanion->回転+.identity->何もしない=回転しない
*/
Instantiate(gameObject,Vector3.zero,Quatanion.identity);
```

### ゲーム内の物体を破壊
オブジェクトを破壊したい場合は、この1文でOK

```c#
Destroy(GameObject);
```

当たったオブジェクトを破壊する例

```c#
void OnCollisionEnter(Collision col){
    Destroy(col.gameObject);
}
```


## ログを残す
例として、自身の位置をコンソール画面に表示するプログラムは下記である。

```c#
Debug.Log(transform.position);
```

また、下記でも同じ結果が得られる。

```c#
print(transform.position);
```

## キーボードから入力を受ける
これはキーボードの入力を受けると「True（正しい）」を返すメソッドです。

```c#
//呼び出され続ける
void Update(){
//もしAを押したならば
 if(Input.GetKeyDown(KeyCode.A)){
  Debug.Log(“key A”);  //「key A」と表示される
 }
}
```
上記はキーボードの「A」を押す毎に、コンソールに「Key A」と表示されるプログラムです。

## ランダム（乱数）
引数のMinとMaxは、MinからMaxまでランダムに返すと思われがちが、実際は**MinからMax未満**で乱数を返す（配列で使いやすいよう）

```c#
//minからmax未満までの値をランダムに返す
Random.Range(Min,Max);
```

例えば、配列に入れた数値をランダムに取り出すこともできます。

```c#
//おもちゃ箱の中に数値が入っている
int[] a = {0,1,2,3,4};
void Update(){
//おもちゃ箱の中身をランダム表示（0からおもちゃ箱の個数未満（4））
Debug.Log( a[Random.Range(0,a.Length)] );
}
```

## 三角関数
数学関係のクラス「Mathf」を利用する。

```c#
//サイン
Mathf.Sin(float);
//コサイン
Mathf.Cos(float);
//タンジェント
Mathf.Tan(float);

//XとYの長さから角度を得る
Matf.Atan2(y,x);

```

例えば、Sin関数を使用した場合、周期的な運動を作ることが出来ます。

```c#
void Update (){
    float sin = Mathf.Sin(Time.time);
    this.transform.position = new Vector3(0,sin,0);
}
```
![](https://i.imgur.com/3vVh89t.gif)



## 時間
1フレームにかかった時間を取得することができ、足していくことで時間を図ることが出来る。

```c#
float timer = 0;
void Update(){
    //あらかじめ用意した変数に代入していく
    timer += Time.deltaTime;
    //timerが3(含まない)以上ならば
    if(timer > 3){
        //足したものをすべてなかったことにする
        timer = 0;
        //3秒ごとに「Time!」と表示される
        Debug.Log(“Time!”);
    }
}
```

## 物理演算
Rigidbodyとは、Unityの物理演算のことで重力や当たり判定、「**力を加える**」などが出来ます。コンポーネントを追加することで物体に対して物理演算を可能にさせます。

```c#
Rigidbody 名前;
void Start(){
    名前 = GetComponent<Rigidbody>();
}
```

## Vecrot3
ベクトルや位置を軸ごとに表したもの。用途が多く、キャラクターや物体の移動にも用いることが出来ます。

```c#
Vector3 名前 = new Vector3(X,Y,Z);
```

物体を動かす簡単なものとして、下記のような方法があります。

```c#
//(10,-20,30)の位置に移動する
VVector3 v = new Vector3(10,-20,30);
transform.position = v;
```
これは、もともと(0,0,0)にあった物体が(10,-20,30)に瞬間移動するプログラムになります。

もしターゲットの場所にプレイヤーを動かしたい場合は、自分のいる場所と移動させたい場所を考え、ベクトルで考えるといいでしょう。こんな感じで↓

![](https://i.imgur.com/V2flLNo.jpg)

## Transform
位置や回転量、大きさ、親子関係など幅広く使うことが出来ます。また、「transform」と書くことで自身のTransformのことを指すことが出来ます。

- transform.position 自身の座標が取得できる
- transform.rotation　自身の回転量が取得できる
- transform.SetParent(Transform);　自身の親を設定できる

## GameObject
ゲームに存在する物体のことを表し、ゲームに存在するすべての物体は「GameObject」で表すことができます。

```c#
//空のGameObjectをゲーム内に生成する
//生成された物体の名前は「なまえ！」になる
GameObject obj = new GameObject(“なまえ！”);
```

## 移動
### ポジション移動
これは毎フレームごと位置を直接変更しているため、瞬間移動をしつつ移動しているイメージ。

```c#
void Update(){
    //rightやleftなども存在する
    transform.position += transform.forward;//正面に1移動
}
```

物体の正面方向に移動するというプログラムになります。右に移動したい場合は、「transform.right」というように「.」の後を変えることで方向も変えることが出来ます。

```c#
void Update(){
    transform.position += new Vector3(0,1,0);//= Vector3.up;と同様
}
```

これだと、物体の向きに関係なく上に移動します。

```c#
void Update(){
    this.gameObject.transform.Translate(1,1,1);
}
```

transform.Translateは現在の位置からどれだけ移動するかというものです。
上のように書くと毎フレームごとにx,y,z全ての方向に1ずつ動きます。



### 物理演算移動
Rigidbodyを使用して移動させるものです。まずは、**inspectorの下のAdd Component→Physics→Rigidbodyを押し、設定しましょう**。

```c#
Rigidbody rb;
void Start(){
    rb = GetComponent<Rigidbody>();
}
```

#### 力を加える移動

```c#
void Start(){
    rb = GetComponent<Rigidbody>();
    rb.AddForce(1,1,1);//rb.AddForce(new Vector(1,1,1))でも可能
}
```
こうするとx,y,z方向に1ずつの力を加えることになります。

#### 移動速度変更
移動速度は物理演算であるため、これも同様にRigidbodyを使います。

```c#
void Update(){
    rb.velocity = transform.forword;//前方向への速度を書き換える
}
```
Rigidbody.velocityとは、｢Rigidbodyの速度ベクトル｣です。公式的には非推奨の動かし方になります。なぜなら、現実的な動きじゃないから、、、だそう。

## 回転
### Rotate（）

```c#
transform.Rotate(X,Y,Z);
```

一番わかりやすいメソッドで、現在の回転量から何度回転させるかを指定することができます。Z→X→Yの順番で回転するため、**同時に2つの軸は回さない方が混乱しません**。

```c#
void Update(){
    transform.Rotate(0,0,1); //Z軸に回り続ける
}
```
これは、Z軸方向に回り続けるプログラムです。

### AngularVelocity
回転する速度を変更することで回転させる方法で、慣性力が働くため、**回りにくく止まりにくい**という特徴を持ちます。

```c#
Rigidbody rb;
void Update(){
     rb.angularVelocity = new Vector3(0,0,5);//速度5で回転
     rb.angularVelocity += new Vector3(0,0,5);//速度5で加速
}
```

### Quaternion
Quaternionが使用される時、99%は次の6つで回転を取得します。

```c#
transform.rotation = Quaternion.関数;
```

#### Quaternion.identity 
何も回転しない状態を表すため、inspectorのrotationは0,0,0になります。

```c#
transform.rotation = Quaternion.identity;
```
#### Quaternion.Euler(X,Y,Z)
引数に軸ごとに回転したい値(0~359)を返します。

```c#
transform.rotation = Quaternion.Euler(0,90,0);//90度Y軸回転
```

#### Quaternion.Angle(Quaternion,Quaternion)
2つの回転の間の角度を返します。

```c#
float angle = Quaternion.Angle(transform.rotation,Quaternion.identity);
```

#### Quaternion.Slerp(Quaternion,Quaternion,float)
2つの回転の間の角度を、0~1の割合で補間して返します。

```c#
//現在の回転から無回転までのうち、0.5の割合で補間
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.identity,0.5);
```

#### Quaternion.LookRotation(Vector3,Vector3)
第1引数に正面方向、第2引数に回転時の頭上方向を指定します。
（第2引数をVector3.downにすると、逆さまになります。）

```c#
public Transform target;
void Update()
{
    Vector3 lookTarget = target.position - transform.position;
    //
    transform.rotation = Quaternion.LookRotation(lookTarget, Vector3.up);
}
```

#### Quaternion.FromToRotation(Vector3,Vector3)
第1引数から第2引数への回転を作成します。

ワールド空間で Transform を回転させ、座標の 1 つ、例えば、y 座標をターゲットの方向 toDirection に向かせるために使用します。

```c#
transform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward);
```

# 備考
途中から動画面倒くさくなっていれてないけど、説明するときは実際に動かしたものを見せたりすると理解が深まります。

そんでもって、自分が分かっている体で話すと、0からスタートの人は頭の中が？？？だらけにしかなりません。

なので、==なるべくかみ砕き、例えやイメージ、動画を入れる==といいでしょう。