一定時間ごとにプレハブからオブジェクトを生成し続けるスポナー(Spawner)を実装します。時間計測・Instantiate()・親子関係を組み合わせて、ゲームでよく使われる「敵やアイテムが湧く」仕組みの基本を作ります。
Time.deltaTime の累積で経過時間を計測できる[SerializeField] で生成間隔をパラメータ化できるInstantiate() でオブジェクトを動的に生成できるRandom.Range() でランダムな値を生成できるHierarchy ビューを右クリックして Create Empty を選択し、空の GameObject を作ります。名前を Spawner に変更し、Position を (X=0, Y=0, Z=0) に設定します。

次に、Inspector ビューの Add Component から Spawner スクリプトを新規作成してアタッチします。
スポナーの核心は「一定時間が経過したかどうかの判定」です。Time.deltaTime(前フレームからの経過秒数)を毎フレーム加算し続けることで、経過時間を計測できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Spawner.cs
using UnityEngine;
public class Spawner : MonoBehaviour
{
private float _elapsed; // 経過時間(秒)
private void Update()
{
_elapsed += Time.deltaTime;
if (_elapsed >= 1f)
{
_elapsed -= 1f;
Debug.Log("1秒経過");
}
}
}
_elapsed に Time.deltaTime を加え続けると、1秒後に _elapsed >= 1f が true になります。その時点で _elapsed -= 1f と差し引くことで超過分が次のサイクルに持ち越され、1秒ごとに繰り返し処理を実行できます。
生成間隔をコード内に固定で書かず、[SerializeField] で Inspector から調整できるようにします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Spawner.cs
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField]
private float _interval = 1f; // 生成間隔(秒)
private float _elapsed;
private void Update()
{
_elapsed += Time.deltaTime;
if (_elapsed >= _interval)
{
_elapsed -= _interval;
Debug.Log("スポーン");
}
}
}

_interval の値を Inspector から変更するだけで、生成間隔を自由に調整できます。
スポナーが生成するアイテムをプレハブとして用意します。
Item にする| プロパティ | 値 |
|---|---|
| Rotation | X=45, Y=45, Z=45 |
| Scale | X=0.5, Y=0.5, Z=0.5 |
Item を Project ビューへドラッグ & ドロップしてプレハブ化するItem は削除する
[SerializeField] でプレハブを受け取るフィールドを追加し、Instantiate() で複製します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Spawner.cs
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField]
private float _interval = 1f;
[SerializeField]
private GameObject _original; // 複製元のプレハブ
private float _elapsed;
private void Update()
{
_elapsed += Time.deltaTime;
if (_elapsed >= _interval)
{
_elapsed -= _interval;
Instantiate(_original, transform.position, Quaternion.identity);
}
}
}

Inspector ビューの Original 欄に、作成した Item プレハブを設定します。実行すると _interval 秒ごとに Item がスポーナーの位置に生成されます。
⚠️
_originalがnull(Inspector でNoneのまま)だと実行時エラーになります。必ずプレハブを設定してから実行してください。
Instantiate(_original, transform.position, Quaternion.identity) とすることで、スポナーオブジェクトの位置にアイテムが生成されます。スポナーを複数配置すれば、それぞれの位置から独立してスポーンします。
Instantiate() の戻り値からコンポーネントを取得して、生成直後のオブジェクトを操作できます。Random.Range() で毎回異なる方向に飛ばしてみましょう。
Random.Range() — 指定した範囲内のランダムな値を返します。
書式:Random.Range メソッド
1
public static float Range(float minInclusive, float maxInclusive);
| パラメータ | 説明 |
|---|---|
minInclusive |
最小値(この値を含む) |
maxInclusive |
最大値(この値を含む) |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Spawner.cs
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField]
private float _interval = 1f;
[SerializeField]
private GameObject _original;
private float _elapsed;
private void Update()
{
_elapsed += Time.deltaTime;
if (_elapsed >= _interval)
{
_elapsed -= _interval;
var item = Instantiate(_original, transform.position, Quaternion.identity);
var rb = item.GetComponent<Rigidbody>();
var x = Random.Range(-5f, 5f);
var y = Random.Range( 3f, 10f);
var z = Random.Range(-5f, 5f);
rb.AddForce(new Vector3(x, y, z), ForceMode.Impulse);
}
}
}
ForceMode.Impulse は「瞬間的な力」を意味します。AddForce の既定は継続的な力(Force)ですが、Impulse を指定すると1フレームで一気に速度が乗り、ボールを蹴るような動きになります。

実行すると、毎回異なる方向にアイテムが飛び出します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField]
private float _interval = 1f;
[SerializeField]
private GameObject _original;
private float _elapsed;
private void Update()
{
_elapsed += Time.deltaTime;
if (_elapsed >= _interval)
{
_elapsed -= _interval;
var item = Instantiate(_original, transform.position, Quaternion.identity);
var rb = item.GetComponent<Rigidbody>();
var x = Random.Range(-5f, 5f);
var y = Random.Range( 3f, 10f);
var z = Random.Range(-5f, 5f);
rb.AddForce(new Vector3(x, y, z), ForceMode.Impulse);
}
}
}
シーンに Spawner オブジェクトを複数配置し、それぞれが独立した位置からスポーンすることを確認してください。
ヒント: Spawner オブジェクトを右クリック → Duplicate で複製し、Position を変えるだけで完成します。transform.position を使って生成しているため、各スポナーが自分の位置で生成します。
スポナーから出現するアイテムの最大数を設定し、上限に達したらスポーンを停止してください。アイテムが破棄されて上限を下回ると、再びスポーンを再開します。
ヒント: Instantiate() に transform を親として渡すと(Instantiate(_original, transform))、生成したアイテムは Spawner の子オブジェクトになります。子が破棄されれば transform.childCount も減るため、「現在の出現数 = transform.childCount」として管理できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField]
private float _interval = 1f;
[SerializeField]
private GameObject _original;
[SerializeField]
private int _maxCount = 5; // 最大出現数
private float _elapsed;
private void Update()
{
_elapsed += Time.deltaTime;
if (_elapsed >= _interval)
{
_elapsed -= _interval;
if (transform.childCount >= _maxCount) return; // 上限チェック
var item = Instantiate(_original, transform); // Spawner の子として生成
item.transform.position = transform.position; // スポナー位置に配置
var rb = item.GetComponent<Rigidbody>();
var x = Random.Range(-5f, 5f);
var y = Random.Range( 3f, 10f);
var z = Random.Range(-5f, 5f);
rb.AddForce(new Vector3(x, y, z), ForceMode.Impulse);
}
}
}
アイテムが OnTriggerEnter などで Destroy() されると子から除外され、transform.childCount が減ります。上限を下回ると再びスポーンします。
通常アイテムとは別に、低確率でラッキーアイテムをスポーンさせてみましょう。
ヒント: Random.Range(0f, 1f) は 0.0〜1.0 の乱数を返します。例えば < 0.1f の条件にすれば 10% の確率になります。ラッキーアイテム用のプレハブを [SerializeField] で別に用意し、確率によって Instantiate() するプレハブを切り替えます。
1
2
3
4
5
6
7
8
9
[SerializeField]
private float _luckyChance = 0.1f; // ラッキーアイテムの出現確率(10%)
[SerializeField]
private GameObject _luckyItem;
// スポーン時の処理内で
var prefab = Random.Range(0f, 1f) < _luckyChance ? _luckyItem : _original;
Instantiate(prefab, transform.position, Quaternion.identity);
_elapsed += Time.deltaTime の累積で経過時間を計測できる[SerializeField] で生成間隔や複製元プレハブを Inspector から設定できるInstantiate(original, position, rotation) でスポナーの位置にオブジェクトを生成できるRandom.Range() で毎回異なる値を取得して動きにばらつきを持たせられるInstantiate(original, transform) で親子関係を使い、出現数を childCount で管理できる_elapsed += Time.deltaTime を毎フレーム実行すると、_elapsed の値はどのように変化しますか?Instantiate(_original) と Instantiate(_original, transform.position, Quaternion.identity) の違いは何ですか?transform.childCount で管理するとき、アイテムを Instantiate する際に何を変える必要がありますか?_original と同じ位置(多くの場合は原点)に生成される。後者はスポナー自身の位置(transform.position)に生成される。Instantiate(_original, transform) のように親 Transform を渡して、生成したオブジェクトを Spawner の子にする必要がある。