【Unity入門】プログラマーがとりあえずコーディングできるためのUnityプログラミング入門

:::note warn
2025/4/24 公開から3年が経ち、読み返してみると **かなり表現が雑** (並行・並列処理の誤用など）で強く反省しています。
近々全面的に書き直します。
:::

## この記事は
プログラマーがUnityでそこそこゲームだったりシミュレーションだったりが作れるようになるための記事です。

前書きが長くなってしまったのですが、本体のみ興味ある方は次のh2タグの「環境構築」まで飛ばしてください。

### 「プログラマー」の定義
本記事の想定読者の技術力はそんなに高くありません。
C#じゃなくともPythonでもなんでもいいので、
* 型
* for文
* if文
* クラス
* （値渡しではなく）参照渡し
が分かってれば困らないと思います。

### 前置き
学科では五月祭（学祭！ぜひ来てね！）にシミュレーションを展示をしたいという話になったりと、僕の周りにUnityを使い始めようという人が同時多発していて、その人たち向けの教材を模索していました。世の中のUnity教材はC#の文法からご丁寧に始まったり、（デザイナー向けに）Unityエディタ画面の操作に終始したりと**プログラマーが手早く参戦できる教材**があまりないように思います。僕のようなゲームエンジニア志望ならまだしも、みんなは本をやりこんでまでガッチリUnityをやりたいわけでもない。
なので、**プログラマー**が**手早く**、**Unityプログラミングの要点**を把握し、**ググりながら開発できるようになる**記事を目指します。

### なぜUnityを使うか
#### ノーコードで色んなことができる
一番読みやすいコードとはノーコードであるという金言をどこかで見たことがある気がします（なかったら僕が言ったことにします）

エディタ画面を見ればすぐに分かることですが、わざわざコード内の数値を調整しなくとも、**直観的な操作でオブジェクトの位置関係を調整できます。**
![sasa_20230214_224813.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/75df4d37-4ba0-d844-d22d-79a34eaaf24e.gif)
こんな感じに、プログラマーがパラメーター調整欄を用意して、**非プログラマーでも気軽に調整できるプラットフォーム**もできちゃいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/9aff7337-a25e-8ead-82df-1b1318a9192b.png)
また、プログラマーが書いたコードはこんな感じにドラッグ&ドロップするだけでオブジェクトに適用できます。（後述）
![sasa_20230214_225757.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/50058afc-a038-2ec9-d0ee-44ef5ab575f7.gif)
これにより、（ぶっちゃけプログラミングの知識がなくとも、）**購入したり他人が書いてもらったコードを簡単に適用することも、外したりすることもできます。**

簡単にまとめると、**デザイナーなど非プログラマーでも参画でき**、なおかつ**プログラマーもラクできる**という利点ですね。

#### スーパー並列マシーン

:::warning
厳密な「並列処理」ではなく、「別々に書いたコードがどうしてか並列して動いているように見える」という意味です。実際は直列です。
:::

Unityプログラミングは**すごいオブジェクト指向**です。

ゴミみたいな図を用意しました。
NPCに話しかけるプレイヤーと話しかけられるNPCの図です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/054b17fd-2976-77d1-bbf5-211d1d4794d7.png)
１からゲームやらを作るとなると、それぞれのクラスを同時に走らせるためのフレームワークを書かないといけません。
しかし、Unityによって、上図の青の部分だけ書けばいいんですね。「移動する」の処理だけ書いておいて、あとはUnityに任せれば自動的にそのコードを走らせてもらえます。

#### 描画マシーン
描画の処理自分で書くのダルいので、その意味でもUnity使う価値は大いにありますよね。

### 「プログラミングできること」と「Unityプログラミングできる」ことの乖離

プログラミングができるからといって、すぐにノー勉でUnityプログラミングに参戦できるかというと、ちょっと難しいです。

Unityは**大規模フレームワーク**であり、**コンポーネント指向のやべー奴**であり、**スーパー並行処理マシーン**であることを心構えておく必要があります。

例として、下記が単純に「指定されたスピードで進み続ける」プログラムです。
```C#:Advancer.cs
using UnityEngine;

public class Advancer : MonoBehaviour
{
    [SerializeField] private Vector3 speed;

    //毎フレーム呼ばれる
    void Update()
    {
        //進む
        transform.position += speed * Time.deltaTime;
    }
}
```
これでエディタ画面ではこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/7696aeee-30d3-2f2a-9b41-2020075b26c4.png)

それで、こうなります。

![sasa_20230214_234436.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/bccfb357-1337-9452-dad9-decd81529ee9.gif)

初見なら、コード見てこう思うと思います。
* UnityEngineネームスペースってなんや
* その継承してるMonoBehaviourクラスってなんや
* SerializeFieldってなんや
* へーVector3ってのがあるんやな
* Update()関数定義しただけでなんで動くん？
* transform未定義で急に出てきたやん
* Time.deltaTimeってなんや
発見がたくさん出てきますね。

上記のものは全てC#の文法ではなく、**Unityオリジナルの機能**になっています。すなわち、Unityプログラミングを不自由にこなすためには、**Unity固有の機能、クラス**を把握しておく必要があります。

この記事は入門ですので、ここでは**覚えるべきもの**と**覚えなくていいもの**を切り分け、**覚えるべきもの**について**ググりながら実装できる**レベルを目指します。

## 環境構築
解説されつくされているので省略します。
* Unity HubとUnityエディタ（バージョンはLTS=Long Term Supportだったらなんでもいい）
* ~~Visual Studio（VSCodeではない）~~

:::note
2024追記

`VSCode`の発展により`Visual Studio`を使う必要がなくなりました。
導入手順: https://code.visualstudio.com/docs/other/unity
:::

~~をインストールし、頑張って**UnityエディタとVisual Studioを連携させる設定をしてください**　
参考：https://qiita.com/engr_murao/items/b7bbb0eaa48f1c66fc2b~~

## コードを適用するまで
そもそも、どうやって書いたコードを反映させるのでしょうか。剣を買っても装備しないと意味がないように、コードを書いただけでは

先述のコードをコピペして適用するから始めましょう（再掲）
```C#:Advance.cs
using UnityEngine;

public class Advancer : MonoBehaviour
{
    [SerializeField] private Vector3 speed;

    //毎フレーム呼ばれる
    void Update()
    {
        //進む
        transform.position += speed * Time.deltaTime;
    }
}
```

### スクリプトファイルを作る
`Project`（デフォルトでは下のファイルがあるところ）に右クリックして、Create → C# Scriptで空のスクリプトファイルを作れます。
ここで、**絶対にファイル名を`Advancer`にしてください。** というのは、**ファイル名とクラス名が一致しないとUnityが認識されません。**
![sasa_20230215_000751.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/08e6c4f2-7449-27a7-d659-1b548cb8620f.gif)

できたファイルをダブルクリックするとスクリプトエディタが開かれますので、上記スクリプトをコピペしてください。

### オブジェクトを作る
とりあえずキューブを出現させてみましょう。

`Hierarchy`（デフォルトなら左のオブジェクト一覧があるところ）に右クリックして、3D Object→Cubeをクリックすることで出現させることができます。
![sasa_20230215_001944.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/490d84bf-01b4-ca91-80dd-3b709fc24686.gif)

### コードを適用する
このキューブが移動できるようにさせるには、**このコードをキューブにアタッチ（＝憑依）させます**

アタッチのやり方は簡単。
AdvancerファイルをCubeにドラッグ&ドロップするだけです。
![sasa_20230215_002644.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/62144bb0-1de8-a742-8560-b18fbac9bf14.gif)
右下にチョロッと「Advancer」の項目が増えているのが分かりますね。

### パラメーターを調整
Cubeを選択してから、`Inspector`（デフォルトなら右）を見ると、下にAdvancerが追加されていますね。
そこでSpeedを調整できます（そういうコードなので）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/d43f2541-8983-bafd-cd1a-e2ce1f34e3ad.png)
好きな数字にでもしてください。

### 実行
上の再生ボタンで動かすことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/d77722be-89b3-5046-f04c-d969b7c11faf.png)

エディタの操作はこれさえわかってれば大丈夫です。

## コンポーネント指向
いよいよコーディングのお話です。

Unityはコンポーネント指向を採用しています。
さきほどのCubeを選択して、`Inspector`を見てみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/3a909662-174f-12e9-3d8f-5d804d510e42.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/36b0cf6a-77b7-f1fe-729c-52b4f2027c94.png)
この項目の一つ一つが、このCubeについている**コンポーネント**なのです。

[コンポーネント](https://ejje.weblio.jp/content/component)とは、そのオブジェクトが持つ**機能**のことです。
このCubeのコンポーネントを図示すると、こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/8edd2a33-7f60-d20b-73fe-5dbd7386e2ee.png)
一つ一つのコンポーネントが、このCubeの処理を果たしているのですね。

`Transform`は必須コンポーネントなので消せませんが、例えば`MeshFilter`か`MeshRenderer`を消してみる（右クリックでできます）と、キューブが透明になってしまいますね。

先ほどやった**アタッチ**とは、すなわち**コンポーネントを一つ付与した**ということになります。

つまるところ、**Unityプログラミングとは、コンポーネントを作っていく**ということに集約できます。（嘘で、シェーダー書いたりすることもあるのですが、基本的にはこの認識で大丈夫です）

そして、コーディング面においても、**他コンポーネントを参照**することが頻出します。
例えば、オブジェクトの座標は先ほど出てきた`Transform`コンポーネントを参照します。

### 把握すべきもの

もちろん全てのコンポーネントを覚える必要性は全くなく、下記の基本コンポーネントだけ把握しておけばコーディングには困らないです。
* `Transform`
    ＝位置・大きさ・回転をつかさどる **全てのオブジェクトに与えられている**
* `Collider`
    ＝当たり判定をつかさどる
* `RigidBody`
    ＝物理演算をつかさどる

あとは、必要性に応じてググれば大丈夫です。

### Transformコンポーネント

ここで、先ほどのスクリプトを見てみましょう。（再掲）
```C#:Advance.cs
using UnityEngine;

public class Advancer : MonoBehaviour
{
    [SerializeField] private Vector3 speed;

    //毎フレーム呼ばれる
    void Update()
    {
        //進む
        transform.position += speed * Time.deltaTime;
    }
}
```
進む部分がこれでちょっとわかりますね。
```
transform.position += speed * Time.deltaTime;
```
の部分。`transform`とは、'Transform`コンポーネントのことです。
その`Transform`クラスの`position`変数、すなわち座標に、スピード（ベクトル）*時間＝道のりを足し算してる、ということなんですね。（右辺については次のh2タグで）

そう、**１コンポーネントに１クラス**が書かれています。実際にこのAdvancerクラスもそうですね。
`Transform`コンポーネントに`Transform`クラスがある、ということですね。

ちなみにこのスクリプトで`transform`変数が未定義で使えたのは継承元の`MonoBehaviour`が定義してくれているだけで、他のコンポーネントはこのようにはいきません。
後述の`GetComponent()`関数でもって他コンポーネントを参照します。

### Collider、Rigidbodyコンポーネント
試しに、キューブに`Rigidbody`コンポーネントをアタッチしてみましょう。
![sasa_20230215_010532.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/00d85e07-e1b6-1d6c-6037-517ef7bb1c55.gif)

`Rigidbody`は物理演算を担うので、再生すると重力で落ちます。

`Collider`コンポーネントは当たり判定ですが、ちょっとめんどくさいことに **`Collider`
コンポーネントをつけただけではすり抜けちゃいます**
「オブジェクト同士がぶつかったときの挙動」は`Rigidbody`の仕事なので、`Rigidbody`をつけないとダメ、ってわけですね。

## 把握すべきクラス
上記では把握すべきコンポーネントについて書きました。
各コンポーネントには１クラスあるので、特に`Transform`クラスは把握していないといけないというのは言うまでもありません。

それに加え、下記クラスを把握しておくと自由度が爆上がりします。
* `GameObject`クラス
　＝オブジェクトそのもの。各インスタンスが各オブジェクト、あるいはプレハブ（後述）を参照している。**超重要**
* `Time`クラス
  ＝時間に関する情報が保持されている。まあ`deltaTime`変数だけ覚えとけば大丈夫かもしれない
* `Vector3`クラス
  =[ベクトル](https://examist.jp/category/mathematics/space-vector/)を表現するクラス。スピードなどの有効線分として使われ方もあれば、位置座標のように位置ベクトルとして使われるケースもあるし、単純に大きさや回転など「x,y,zの３つ数字が並んだセット」という使われ方もされている。近頃数学Bから数学Cに移行するようなので、ベクトル自体の説明もいずれ必要になるだろうか。
* `Quanternion`クラス
　＝ベクトルに関する回転計算。難しい。こちらの記事がオススメ：https://qiita.com/drken/items/0639cf34cce14e8d58a5
* `Mathf`クラス
  ＝各種数学の関数（sin, cos, absなど）を提供。
* `Debug`クラス
　＝デバッグ用。特にコンソールデバッグができる`Debug.Log()`が多用されるが、[ブレークポイントを貼ってゲームを止めてデバッグする方がかっこいいとされている](https://docs.unity3d.com/ja/2018.4/Manual/ManagedCodeDebugging.html)。
* `Input`クラス
　＝キー入力の取得用。`Input.GetKey("a")`は「A」キーが押されたら`true`、押されていない間は`false`を返す関数である。

覚えることがたくさんあって大変ですね。最悪全部忘れてもいいので`GameObject`だけは覚えておいてください。後述しますが頻繁に使います。

これらの存在だけを知っておくと、あとはググればなんとかなると思います。

これで理解がアンロックされますね。
```C#:Advancer.csの一部
transform.position += speed * Time.deltaTime;
```
の部分。`speed`の型は`Vector3`クラス。そして`Time.deltaTime`は「１フレーム（後述）にかかった時間」
そうやって「速度（ベクトル）」＊「時間」＝「移動量（ベクトル）」を、`Transform.position`に足し算している、というわけです。

## 把握すべき関数
**自作するコンポーネントは全て`MonoBehaviour`クラスを継承します。（継承しないとエラー発生します）**
`MonoBehaviour`クラス自体は深く知らなくとも大丈夫なのですが、**`MonoBehaviour`クラスが持っている関数をオーバーライドすること**が頻出です。（というか動かすためには基本的にそうします）

その`MonoBehaviour`クラスの把握しておくべき関数には下記があります。
* `Start()`
　＝最初のフレームの一回だけ呼ばれる。初期化などに使う
* `Update()`
　＝毎フレーム呼ばれる。
* `GetComponent()`
  ＝他コンポーネントを返す。使い方は後述参照。
* `OnCollisionEnter()`
　＝Colliderコンポーネント持ちとRigidbodyコンポーネント持ちのオブジェクトが衝突したら呼ばれる。当たり判定の処理に使う。

他の関数はあまり使いませんが、気になる場合は[こちらを参照。](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html)

フレームとは：https://ekulabo.com/frame-meaning
簡単に言うと、ゲームの処理は各処理のループなのですが、１ループのことを１フレームと呼んでいることですね。

`Start()`と`Update()`はとても重要ですね。
新規でスクリプトファイルを作成した際にデフォルトで書かれているぐらいには重要です。

先述のスクリプトの理解がもっとアンロックされました。
```C#:Advancer.csの一部
//毎フレーム呼ばれる
void Update()
{
    //進む
    transform.position += speed * Time.deltaTime;
}
```
の部分。
`Update()`関数の中に「進む」処理を書いているので、**この処理が毎フレーム発生している**ということになりますね。簡単に言うと、[常に進み続けるということです。](https://www.youtube.com/watch?v=qrz_DlLYNOc)

## 把握すべき機能

その他、コーディングにおいて知っておきたいUnity特有の機能が一つあります。
`SerializeField`です。

メンバー変数の定義にあった
```C#:Advancer.csの一部
[SerializeField] private Vector3 speed;
```
の部分。
「`SerializeField`」属性をこのように`speed`変数に付与することによって、**エディタ上から数値を調整できるようになります**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/d43f2541-8983-bafd-cd1a-e2ce1f34e3ad.png)

実は、`public`で変数を定義すると`SerializeField`指定しなくとも同様のことができますが、一般的に`public`変数を定義するとロクなことにならないと言われているので、`SerializeField`を推奨します。

## コーディングしよう！１
各概念の表面を撫でたので、実際のコーディングでこれまで学んだことの具体化を試みます。
### 回転する
![ezgif-5-1993f6f430.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/5517e313-9473-754c-4321-1fffb245b6e9.gif)
```C#:Rotater.cs
using UnityEngine;

public class Rotater : MonoBehaviour
{
    [SerializeField] private Vector3 angularSpeed;

    void Update()
    {
        transform.rotation *= Quaternion.Euler(angularSpeed * Time.deltaTime);
    }
}
```
`transform.rotation`はオブジェクトの回転を保持しています。**`Quanternion`を`Quanternion`で回転するのには、掛け算をします。**
`Quanternion.Euler`は、xyz軸の普通の角度を、`Quanternion`に直す関数です。
これによって、エディタからxyzで入力した角速度で回転するようになります。
ちなみに、回転する部分はこんな書き方もできます。
```C#
transform.Rotate(angularSpeed * Time.deltaTime);
```
同様の処理をしています。

今まで覚えてきた関数以外に`Quanternion.Euler`やら`transform.Rotate`やらいろいろ知らないものが出てくるやんけふざけんなとお思いかもしれませんが、これらは覚える必要は全くなく、「Unity 回転」とでも**ググればすぐ出てきます。**また、[Unity公式スクリプトリファレンス](https://docs.unity3d.com/ja/2019.4/ScriptReference/Transform.html)に**各クラスがどんなメンバー変数・関数を持っているのか**が明記されています。
ここで大事なのが、「回転の情報は`Transform`コンポーネントが持っているから`Transform`のスクリプトリファレンスを見ればいいや」と調べる検討がつくことかなと思っています。

### キー入力に応じて移動
典型的なwで前進、adで回転(方向転換)するスクリプトを書いてみましょう。
![sasa_20230215_164258.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/2cd76432-6147-98bd-19f1-9d78ad191802.gif)


```C#:Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Controller : MonoBehaviour
{
    [SerializeField] private float speed;
    [SerializeField] private float angularSpeed;

    void Update()
    {
        //wが押されたら前進
        if (Input.GetKey("w"))
        {
            //前進
            transform.position += transform.forward * speed * Time.deltaTime;
        }

        //aが押されたら左回転
        if (Input.GetKey("a"))
        {
            //左回転
            transform.rotation *= Quaternion.Euler(transform.up * (-angularSpeed) * Time.deltaTime);
        }

        //dが押されたら右回転
        if (Input.GetKey("d"))
        {
            //左回転
            transform.rotation *= Quaternion.Euler(transform.up * angularSpeed * Time.deltaTime);
        }
    }
}
```

`transform.up`は「オブジェクトから見て上方向」のベクトル（回転の回転軸に使用）、`transform.forward`は「前方向」のベクトルを返します。（前進に使用）

### 他コンポーネントを参照する
今度は他のコンポーネントから数値を寄越してきたり、他コンポーネントのメソッドを呼ぶプログラムを書きましょう。

まずは、呼ばれる側。
```C#:ComponentA.cs
using UnityEngine;

public class ComponentA : MonoBehaviour
{
    public string variable = "どりゃあああああ";

    //呼ばれる関数
    public void Log()
    {
        Debug.Log("でりゃああああああ");
    }
}
```

次に、呼ぶ側。
```C#:ComponentB.cs
using UnityEngine;

public class ComponentB : MonoBehaviour
{
    private void Start(){
        GetComponent<ComponentA>().Log();
    }
}
```

両方ともキューブにアタッチすると、コンソールにこう表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/cc2bc419-cfed-713c-4f31-d9495db5aca1.png)


ここで大事なのは`GetComponent()`です。
`GetComponent<コンポーネントのクラス名>()`
で、自分のオブジェクトの他コンポーネントを参照することができます。

### 他オブジェクトを参照する
今度は、上記のスクリプトを真似て、他オブジェクトのコンポーネントを読んでみましょう。

```C#:ComponentA.cs
using UnityEngine;

public class ComponentA : MonoBehaviour
{
    public string variable = "どりゃあああああ";

    //呼ばれる関数
    public void Log()
    {
        Debug.Log("でりゃああああああ");
    }
}

```
上記スクリプトをCubeAにアタッチ。

```C#:ComponentB.cs
using UnityEngine;

public class ComponentB : MonoBehaviour
{
    [SerializeField] private GameObject targetObject;

    // 最初のフレームだけ
    void Start()
    {
        //ComponentAを参照
        ComponentA componentA = targetObject.GetComponent<ComponentA>();

        //componentA.variableをコンソールに表示
        Debug.Log(componentA.variable);

        //関数を呼ぶ
        componentA.Log();
    }
}
```
上記スクリプトをCubeB（生成してください）にアタッチ。

ここで、CubeAをCubeBの`targetObject`にドラッグ&ドロップしてください。
![sasa_20230215_165833.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/908cff8e-e6cb-9535-97f8-d1fda6095224.gif)
すると先ほどと同じ結果を得られます。


前述のように、`GameObject`型はオブジェクトそのものを指します。
これを`SerializeField`することで、他オブジェクトを参照することができます。
先ほどの`GetComponent`単体では**自分の**コンポーネントを返す一方、`GameObject.GetComponent()`は参照しているオブジェクトのコンポーネントを返します。

ちなみに動的にオブジェクトを探して参照したい場合はオブジェクト名で検索する`Find()`関数と、保持しているコンポーネントで探す`FindObjectsOfType`関数などがありますが、`Find()`は非推奨です。オブジェクト名が重複したり変更したりした瞬間にバグるので。

## プレハブ
ここまでは、オブジェクトをエディタ上で設置してから動かすという静的配置でした。
銃オブジェクトが弾オブジェクトを生成して発射するといった**ゲーム中にオブジェクトを生成する動的配置**を実現するには、**プレハブ**の出番となります。

### プレハブとは
いわば、**オブジェクトの設計図**です。

例えば銃が弾を発射する例でいくと、弾プレハブを作り、銃オブジェクトが弾プレハブを保持します。
そして、射撃するときは、銃オブジェクトが弾プレハブを`Instantiate()`(インスタンス化)することで弾オブジェクトを生成します。

設計図の例えでいくと、弾の設計図を持っておいて、射撃する時はその設計図通りに弾を作って発射する、ということですね。

### プレハブ化の操作
やり方は簡単。
まずは、キューブでも何でもいいので、普通に何かオブジェクトを生成してください。

そして、`hierarchy`上のオブジェクトを`Project`にドラッグ&ドロップ。なんか出来たフォルダが、プレハブファイルです。

![sasa_20230215_200302.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/b56579e2-3921-e4a6-5d5f-d0fc0e19ae21.gif)


一度プレハブファイルができたら、ワールド上にあるオブジェクトは削除しても大丈夫です。削除してください。

### プレハブの生成
生成してみましょう。

ワールド上にあるキューブに、**`Rigidbody`をつけてから**、下記をアタッチ。

```C#:Instatiater.cs
using UnityEngine;

public class Instantiater : MonoBehaviour
{
    [SerializeField] private GameObject prefab;

    //毎フレーム呼ばれる
    void Update()
    {
        //生成する
        Instantiate(prefab);
    }
}
```

まずは、プレハブをセットしなければなりません。
これは「他オブジェクトを参照」でやったように、ドラッグ&ドロップでできます。

これでプレイすると、ウミガメの卵みたいにキューブが生成されまくります。(重いですね)

![sasa_20230215_201131.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/c6b26437-3b19-a4c0-6f9c-46ef5e02a9bd.gif)

:::note
`Rigidbody`をつけた理由としては、「物理演算」がないと同じところに生成されまっても、一点に重複しながら生成されるだけなので生成されているのが確認できないからです。
:::

## コーディングしよう！２
### 当たり判定処理
簡単な当たり判定処理を書きます。

当たり屋
```C#:Hitter.cs
using UnityEngine;

//当たり屋
public class Hitter : MonoBehaviour
{
    //当たった時の処理
    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("Hitter当たった！");
    }
}
```

被害者
```C#:Victim.cs
using UnityEngine;

//当てられる被害者
public class Victim : MonoBehaviour
{
    //当たった時の処理
    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("Victim:当たった！");
    }
}
```

上記ができたら「当たり屋」に`Rigidbody`をつけて、「被害者」を「当たり屋」の真下に置いてください。当たり屋が落下したところに被害者が来るように。

![sasa_20230215_202503.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/7cebdb8b-3db5-0cac-b0af-015f76b47b16.gif)


## 説明しきれていない重要概念
* 親オブジェクトと子オブジェクトの関係：オブジェクトには親子関係がありますが、親オブジェクトを動かすと子オブジェクトも動きます。
* Local座標とWorld座標：ワールド全体の絶対的な座標系と、オブジェクトから見た相対的な座標系があります。
* `Invoke()`で、指定時間遅延して関数を呼ぶことができます。
* `UnityEvent`でデリゲート処理ができます。
* `Scene`：ワールド（ないし画面）を複数作れます
* `Animator`でアニメーションを制御できます

## 次回予告
追加執筆予定の記事では、実際に[このようなゲーム](https://konbraphat51.github.io/Dammaku/)を作るまでの工程を書いて、Unityプログラミングの具体例を掴めるようにしたいと思っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/85668193-f3d4-0f28-5104-3b25fa292b21.png)