Unity入門:3Dで的を狙え!Igaguriゲームを作りながら学ぼう!
対象読者:Unity学び始めの方・C#をこれから覚えたい方 このブログでは、実際のIgaguri(いがぐり)ゲームのコードを読み解きながら、Unityの3D物理演算・レイキャスト・パーティクルを学びます。
記事の目次
この記事はやや長めです。目的に合わせてジャンプして読み分けてください。
おすすめの読み方
セクション一覧
ポイント一覧
- ① 2Dと3Dの物理コンポーネントの違い
- ②
Camera.main.ScreenPointToRay()で画面クリックを3D空間の方向に変換する - ③ 公開メソッドでいがぐりを「外から操作する」
- ④
OnCollisionEnter()で3D衝突を検知する - ⑤
isKinematic = trueで物理演算を止める - ⑥
ParticleSystem.Play()でエフェクトを再生する
このゲームで何ができるの?
今回題材にするのは、画面をクリックした方向に「いがぐり」を発射して、的に当てる3Dアクションゲームです。
- 🖱️ マウスでクリックした方向にいがぐりが飛んでいく
- 🌰 いがぐりは物理演算で自然な放物線を描く
- 💥 的に当たると動きが止まり、パーティクル(爆発エフェクト)が再生される

たった 2つのスクリプト(合計約30行) でこれが実現できます。3Dレイキャストと物理演算という、3Dゲーム開発の重要テクニックが凝縮されています。一緒に読み解いていきましょう!
プロジェクトの構成
このプロジェクトのファイル構成はこうなっています。
Assets/
├── IgaguriGenerator.cs # いがぐりを生成・発射するスクリプト
├── IgaguriController.cs # いがぐりの動きと衝突を制御するスクリプト
├── igaguriPrefab # いがぐりのプレハブ(Rigidbody・ParticleSystem付き)
└── _Tanks/ # UnityのTanksサンプルアセット
└── Scripts/ # 的の移動・ゲーム管理スクリプト群chapter7では、UnityのサンプルアセットTanksの上に、オリジナルのいがぐり発射システムを追加しています。サンプルアセットを改造して新機能を組み込む、というゲーム開発のリアルな進め方が体験できます。
コードを全部見てみよう
IgaguriGenerator.cs(いがぐりの生成と発射)
using UnityEngine;
using UnityEngine.InputSystem; // 入力を検知するために必要!!
public class IgaguriGenerator : MonoBehaviour
{
public GameObject igaguriPrefab;
void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
GameObject igaguri = Instantiate(igaguriPrefab);
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.value);
igaguri.GetComponent<IgaguriController>().Shoot(ray.direction * 2000);
}
}
}IgaguriController.cs(いがぐりの物理と衝突)
using UnityEngine;
public class IgaguriController : MonoBehaviour
{
public void Shoot(Vector3 dir)
{
GetComponent<Rigidbody>().AddForce(dir);
}
void OnCollisionEnter(Collision collision)
{
GetComponent<Rigidbody>().isKinematic = true;
GetComponent<ParticleSystem>().Play();
}
void Start()
{
Application.targetFrameRate = 60;
// Shoot(new Vector3(0, 200, 2000));
}
}この2つのスクリプトには、合計6つの学びポイントがあります。順番に見ていきましょう!
ポイント①:2Dと3Dの物理コンポーネントの違い
GetComponent<Rigidbody>().AddForce(dir);chapter6では Rigidbody2D を使いましたが、今回は Rigidbody(3D版) です。
| コンポーネント | 対応する空間 | 主な用途 |
|---|---|---|
Rigidbody2D |
2D(X・Y軸) | 2Dゲームの物理演算 |
Rigidbody |
3D(X・Y・Z軸) | 3Dゲームの物理演算 |
AddForce() の使い方は同じですが、3Dでは Vector3(X・Y・Z の3要素)でベクトルを扱います。これにより、奥行き(Z軸)方向への力も加えられるようになります。
ポイント②:Camera.main.ScreenPointToRay() で画面クリックを3D空間の方向に変換する
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.value);
igaguri.GetComponent<IgaguriController>().Shoot(ray.direction * 2000);これがこのゲームの核心です。画面上のクリック座標(2D)を3D空間の「方向」に変換しています。
画面(2D座標)
↓ ScreenPointToRay()
Ray(カメラから飛び出す光線)
└─ ray.direction = 光線の方向ベクトル(正規化済み)Ray(レイ) はカメラの位置から画面のクリック点を通って3D空間に伸びる「光線」のようなものです。この光線の方向 ray.direction にいがぐりを飛ばすことで、「クリックした方向に発射する」という直感的な操作が実現できています。
ray.direction * 2000 → 同じ方向に、2000倍の力を加える💡
ray.directionは長さ1の正規化されたベクトルです。これに大きな数を掛けることで発射の強さを調整しています。数値を大きくすると速く飛びます。
ポイント③:公開メソッドでいがぐりを「外から操作する」
// IgaguriController.cs
public void Shoot(Vector3 dir)
{
GetComponent<Rigidbody>().AddForce(dir);
}// IgaguriGenerator.cs
igaguri.GetComponent<IgaguriController>().Shoot(ray.direction * 2000);IgaguriController の Shoot() メソッドは public で定義されています。これにより、別のスクリプト(IgaguriGenerator)から呼び出せます。
IgaguriGenerator(発射を指示する側)
└─ .GetComponent<IgaguriController>()
└─ .Shoot(方向ベクトル) ← この橋渡しで2スクリプトが連携メソッドに Vector3 dir という引数を持たせることで、「どの方向に飛ばすか」を呼び出し元が自由に指定できます。発射ロジックと「どこから飛ばすか」の決定を分離した、再利用しやすい設計です。
ポイント④:OnCollisionEnter() で3D衝突を検知する
void OnCollisionEnter(Collision collision)
{
GetComponent<Rigidbody>().isKinematic = true;
GetComponent<ParticleSystem>().Play();
}OnCollisionEnter は3D空間で物体が衝突したときに自動的に呼ばれるメソッドです。
| コールバック | 次元 | 呼ばれるタイミング |
|---|---|---|
OnCollisionEnter |
3D | 物体に物理的に衝突した瞬間 |
OnCollisionEnter2D |
2D | 物体に物理的に衝突した瞬間 |
OnTriggerEnter |
3D | トリガー領域に触れた瞬間 |
OnTriggerEnter2D |
2D | トリガー領域に触れた瞬間 |
何かに当たった瞬間に2つの処理が走ります。
ポイント⑤:isKinematic = true で物理演算を止める
GetComponent<Rigidbody>().isKinematic = true;isKinematic を true にすると、そのRigidbodyは物理演算の影響を受けなくなります。
isKinematic = false(デフォルト)→ 重力・力・衝突の影響を受ける(飛んでいる状態)
isKinematic = true → 物理演算を無視して静止する(刺さった状態)いがぐりが何かに当たった瞬間に isKinematic = true にすることで、当たった場所に「刺さった」ように静止する演出が実現できています。コードを書き換えることなく、実行中に物理状態を動的に切り替えられるのがポイントです。
ポイント⑥:ParticleSystem.Play() でエフェクトを再生する
GetComponent<ParticleSystem>().Play();ParticleSystem はUnityの標準エフェクトシステムです。炎・爆発・煙・きらめきなど、様々な視覚的エフェクトを表現できます。.Play() を呼ぶだけでエフェクトが再生されます。
| メソッド | 動作 |
|---|---|
Play() |
パーティクルを再生する |
Stop() |
パーティクルを停止する |
Clear() |
表示中のパーティクルを消去する |
いがぐりのプレハブに事前に ParticleSystem コンポーネントをアタッチしておくことで、「当たった瞬間に .Play() を1行呼ぶだけ」という非常にシンプルなコードでエフェクトが実現できています。
2つのスクリプトの役割分担
【IgaguriGenerator】 【IgaguriController】
空のGameObjectにアタッチ いがぐりプレハブにアタッチ
↓ ↓
クリックを検知 Shoot()で力を加えて発射
ScreenPointToRay で方向を計算 OnCollisionEnter で衝突を検知
Instantiate でいがぐりを生成 → isKinematic = true で静止
Shoot() を呼んで方向を渡す → ParticleSystem.Play() でエフェクトコードの流れを整理しよう
【IgaguriGenerator の毎フレーム処理フロー】
① クリックされた?
└─ YES → igaguriPrefab を Instantiate(生成)
→ ScreenPointToRay でクリック方向の Ray を取得
→ IgaguriController.Shoot(ray.direction * 2000) を呼ぶ
【IgaguriController の処理フロー】
① Shoot(dir) が呼ばれた時
└─ Rigidbody.AddForce(dir) → 指定方向に力を加えて飛ばす
② 何かに衝突した時(OnCollisionEnter)
└─ isKinematic = true → 物理演算を止めて静止
└─ ParticleSystem.Play() → エフェクトを再生自分でカスタマイズしてみよう!
挑戦①:発射の強さを変える
igaguri.GetComponent<IgaguriController>().Shoot(ray.direction * 2000);
// 3000 にすると速く、1000 にするとゆっくり飛ぶ挑戦②:いがぐりを連射できないようにする
// IgaguriGenerator に変数を追加して、最後の発射から一定時間後だけ発射できるようにする
float cooldown = 0;
void Update()
{
this.cooldown -= Time.deltaTime;
if (Mouse.current.leftButton.wasPressedThisFrame && this.cooldown <= 0)
{
this.cooldown = 1.0f; // 1秒のクールダウン
// ... 発射処理
}
}挑戦③:衝突したオブジェクトの名前をログ出力する
void OnCollisionEnter(Collision collision)
{
Debug.Log("衝突相手: " + collision.gameObject.name);
// ...
}挑戦④:コメントアウトされたコードを試す
void Start()
{
Application.targetFrameRate = 60;
Shoot(new Vector3(0, 200, 2000)); // コメントを外すと起動時に自動発射!
}まとめ
今回のIgaguriゲームから学んだことを整理しましょう。
Rigidbody(3D)はRigidbody2D(2D)と使い方は同じで、3D空間(Vector3)で動作するCamera.main.ScreenPointToRay()で画面クリック座標を3D空間の光線(Ray)に変換できるray.directionは方向ベクトルで、これに大きな数を掛けて発射力にするpublicメソッドに引数を持たせると、呼び出し元から発射方向を柔軟に指定できるOnCollisionEnterは3D物体が衝突した瞬間に自動で呼ばれる(2D版はOnCollisionEnter2D)Rigidbody.isKinematic = trueにすると実行中に物理演算を動的に止められるParticleSystem.Play()を1行書くだけでエフェクトを再生できる
2Dゲームから3Dゲームへの拡張として、座標の扱いが Vector2 から Vector3 になり、ScreenPointToRay という3D特有のテクニックが登場しました。「動く→コードを読む→カスタマイズする」 のサイクルを繰り返すことが、Unity上達の近道です。
次のステップとして、当たった的をカウントするスコア機能や、一定数当てたらゲームクリアになる仕組みを追加してみましょう!
最終更新:2026年4月