FPSの弾の当たり判定を実装したい。
でも、「どうやって実装すればいいのか分からない」そんな風に感じていませんか。
実は、FPSの弾の当たり判定は、Raycastという機能を使うことで実現できます。
Unityを使えば、初心者でもヒット判定システムを作ることができるでしょう。
この記事では、FPSの弾がどう当たるのか、発射からヒット判定までの内部処理を、コピペで動くサンプルコードとともに詳しく解説します。
✨ この記事でわかること
- FPSの弾の当たり判定の基本的な仕組み(所要30分)
- Raycastを使ったヒット判定の実装方法(所要1時間)
- 弾の飛翔処理と物理演算の使い分け(所要1時間)
- FPS弾システムでよくあるエラー5選と解決方法
- 実用的な弾システム完成までの4ステップ(合計5時間)

最初はRaycastを使った瞬間的な当たり判定から始めて、必要に応じて物理演算を使った弾を追加するのがコツです。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
FPSの弾の当たり判定とは?基礎知識から理解する

FPSの弾の当たり判定とは、発射された弾が敵に当たったかどうかを判定する処理のことです。
FPSゲームでは必須の機能です。
FPSの弾の当たり判定には、Raycastと物理演算の2つの方法があります。
Raycastは瞬間的な当たり判定に適しており、物理演算はリアルな弾の飛翔に適しています。
ゲームの性質に応じて、適切な方法を選ぶことが重要でしょう。
FPSゲームでは、プレイヤーが武器を撃つと、弾が飛んで敵に当たる必要があります。
この当たり判定を実装する方法が、Raycastと物理演算の2つ。
Raycastは処理が軽く、多くのFPSゲームで採用されている方法です。
物理演算は、リアルな弾の軌道を実装したい場合に適しています。
FPSの弾の当たり判定に必要な要素
✅ FPSの弾の当たり判定に必要な要素
- Raycast処理:瞬間的な当たり判定を行う処理(所要時間:1時間)
- 物理演算:リアルな弾の飛翔処理(所要時間:2時間)
- ヒット判定:当たった対象を判定する処理(所要時間:30分)
- ダメージ計算:当たった時のダメージを計算する処理(所要時間:30分)
- Raycast処理は、発射した瞬間に当たり判定を行う処理。
- 物理演算は、弾のオブジェクトを作成して、実際に飛ばす処理。
- ヒット判定は、当たった対象が何かを判定する処理。
- ダメージ計算は、当たった時に与えるダメージを計算する処理。
これらの要素を組み合わせることで、本格的な弾システムを実装できます。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
Raycastを使ったヒット判定の実装方法

Raycastを使ったヒット判定を実装する方法を解説します。
ここでは、コピペで動くサンプルコードを紹介します。
実装手順:基本的なヒット判定システムを作る
ステップ1:Raycastの実装(所要30分)
以下のコードで、Raycastを使ったヒット判定を実装できます。
|
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 |
using UnityEngine; public class WeaponController : MonoBehaviour { [SerializeField] private Camera playerCamera; [SerializeField] private float range = 100f; [SerializeField] private int damage = 25; [SerializeField] private LayerMask enemyLayer; void Update() { if (Input.GetButtonDown("Fire1")) { Shoot(); } } void Shoot() { RaycastHit hit; Vector3 rayOrigin = playerCamera.transform.position; Vector3 rayDirection = playerCamera.transform.forward; if (Physics.Raycast(rayOrigin, rayDirection, out hit, range, enemyLayer)) { // 敵に当たった場合 Enemy enemy = hit.collider.GetComponent(); if (enemy != null) { enemy.TakeDamage(damage); } } } } |
配置場所:Playerオブジェクトまたは武器オブジェクトにアタッチ
確認方法:再生ボタンを押して、弾を撃って敵に当たればOK
Raycastは、指定した位置から指定した方向に、見えない線を飛ばす処理です。
この線が敵に当たったかどうかを判定することで、弾が当たったかを確認できます。
rayOriginは、Raycastの開始位置で、playerCamera.transform.positionを使います。
rayDirectionは、Raycastの方向で、playerCamera.transform.forwardを使います。
rangeは、Raycastの最大距離で、100fに設定しています。
enemyLayerは、敵が属するレイヤーで、これに当たった場合のみ判定します。
⚠️ よくあるエラー
- 弾が当たらない → enemyLayerの設定を確認(敵のオブジェクトがenemyLayerに設定されているか)
- Raycastが正しく動作しない → rangeの値を確認(小さすぎると当たらない、大きすぎると処理が重い)
- ダメージが適用されない → Enemyコンポーネントの有無を確認(hit.collider.GetComponent<Enemy>()で取得できるか)
- Raycastの方向がずれる → playerCamera.transform.forwardが正しい方向を向いているか確認
より高度なRaycast実装
基本的なRaycastに加えて、より高度な実装を追加できます。
例えば、弾痕を残す処理や、エフェクトを表示する処理を追加できます。
|
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 |
void Shoot() { RaycastHit hit; Vector3 rayOrigin = playerCamera.transform.position; Vector3 rayDirection = playerCamera.transform.forward; if (Physics.Raycast(rayOrigin, rayDirection, out hit, range, enemyLayer)) { // 弾痕を残す(オプション) if (hit.collider.gameObject.tag == "Wall") { // 弾痕のエフェクトを生成 Instantiate(bulletHoleEffect, hit.point, Quaternion.LookRotation(hit.normal)); } // 敵に当たった場合 Enemy enemy = hit.collider.GetComponent(); if (enemy != null) { enemy.TakeDamage(damage); } } // マズルフラッシュのエフェクト(オプション) if (muzzleFlashEffect != null) { muzzleFlashEffect.Play(); } } |
この実装では、壁に当たった場合に弾痕を残し、発射時にマズルフラッシュを表示します。
これにより、よりリアルな弾システムを実装できます。
複数のRaycastを使った散弾処理
散弾銃のような、複数の弾を同時に発射する処理も実装できます。
|
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 |
void ShootShotgun() { int pelletCount = 8; // 散弾の数 float spread = 5f; // 散弾の広がり for (int i = 0; i < pelletCount; i++) { Vector3 rayOrigin = playerCamera.transform.position; Vector3 rayDirection = playerCamera.transform.forward; // 散弾の方向をランダムにずらす rayDirection += Random.insideUnitSphere * spread; rayDirection.Normalize(); RaycastHit hit; if (Physics.Raycast(rayOrigin, rayDirection, out hit, range, enemyLayer)) { Enemy enemy = hit.collider.GetComponent(); if (enemy != null) { enemy.TakeDamage(damage); } } } } |
この実装では、複数のRaycastを同時に発射することで、散弾銃のような効果を実現します。
Random.insideUnitSphereを使って、散弾の方向をランダムにずらしています。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
物理演算を使った弾の飛翔処理

物理演算を使った弾の飛翔処理を解説します。
リアルな弾の動きを実装したい場合に適しています。
Rigidbodyを使った弾の実装
物理演算を使う場合は、Rigidbodyコンポーネントを追加します。
発射時に力を加えることで、リアルな弾の飛翔を実現できます。
Rigidbody.AddForce()を使うことで、弾に力を加えられます。
|
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 |
public class Bullet : MonoBehaviour { [SerializeField] private float speed = 50f; [SerializeField] private float lifetime = 5f; [SerializeField] private int damage = 25; private Rigidbody rb; void Start() { rb = GetComponent(); rb.velocity = transform.forward * speed; Destroy(gameObject, lifetime); } void OnTriggerEnter(Collider other) { if (other.gameObject.layer == LayerMask.NameToLayer("Enemy")) { Enemy enemy = other.GetComponent(); if (enemy != null) { enemy.TakeDamage(damage); Destroy(gameObject); } } } } |
この実装では、弾のオブジェクトにRigidbodyを追加し、発射時に速度を設定します。
OnTriggerEnterで、敵に当たった時の処理を実装しています。
lifetimeで、一定時間後に弾を自動的に削除します。
Raycastと物理演算の使い分け
Raycastは、瞬間的な当たり判定に適しています。
物理演算は、リアルな弾の飛翔を実装したい場合に適しています。
一般的には、Raycastを使った方法が処理負荷が軽く、多くのFPSゲームで採用されています。
Raycastのメリットは、処理が軽く、実装が簡単なことです。
物理演算のメリットは、リアルな弾の軌道を実装できることです。
ゲームの性質に応じて、適切な方法を選ぶことが重要です。
物理演算の最適化
物理演算を使う場合、パフォーマンスに注意が必要です。
弾の数を制限したり、不要な物理演算を無効化したりすることで、パフォーマンスを改善できます。
また、弾のライフタイムを短くすることで、シーン内のオブジェクト数を減らせます。
物理演算を使う場合は、オブジェクトプールを実装することで、さらにパフォーマンスを改善できます。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
ヒット判定とダメージ処理

ヒット判定とダメージ処理について解説します。
適切に実装することで、本格的な弾システムを作れます。
部位によるダメージの違い
頭や胴体など、部位によってダメージを変える処理を実装できます。
|
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 |
void Shoot() { RaycastHit hit; Vector3 rayOrigin = playerCamera.transform.position; Vector3 rayDirection = playerCamera.transform.forward; if (Physics.Raycast(rayOrigin, rayDirection, out hit, range, enemyLayer)) { Enemy enemy = hit.collider.GetComponent(); if (enemy != null) { string hitPart = hit.collider.tag; int finalDamage = damage; // 部位によるダメージ倍率 if (hitPart == "Head") { finalDamage = damage * 2; // 頭に当たった場合は2倍 } else if (hitPart == "Body") { finalDamage = damage; // 胴体は通常ダメージ } else if (hitPart == "Limb") { finalDamage = damage / 2; // 手足は半分 } enemy.TakeDamage(finalDamage); } } } |
この実装では、当たった部位のタグを確認して、ダメージを変えています。
これにより、より戦略的な戦闘が可能になります。
ダメージ処理の実装
ダメージ処理は、敵のHPを減らす処理です。
|
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 |
public class Enemy : MonoBehaviour { [SerializeField] private int maxHP = 100; private int currentHP; void Start() { currentHP = maxHP; } public void TakeDamage(int damage) { currentHP -= damage; if (currentHP <= 0) { Die(); } } void Die() { // 敵が死亡した時の処理 Destroy(gameObject); } } |
この実装では、TakeDamage関数でダメージを受け取り、HPを減らします。
HPが0以下になったら、Die関数を呼び出して敵を倒します。
また、ダメージを受けた時のエフェクトや音声を追加することで、よりリアルな処理になります。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
FPS弾システムでよくある失敗5選と解決方法

FPS弾システムを実装する際、初心者が陥りやすい失敗があります。
ここでは、5つのよくある失敗と解決方法を紹介します。
失敗1:弾が当たらない
❌ よくある失敗
- enemyLayerが正しく設定されていない
- rangeの値が小さすぎる
- Raycastの方向が間違っている
- 敵のColliderが設定されていない
弾が当たらない場合、enemyLayerの設定やrangeの値を確認することが重要です。
また、敵のColliderが正しく設定されているかも確認しましょう。
✅ 正しいアプローチ
- enemyLayerを正しく設定する(敵のオブジェクトがenemyLayerに設定されているか)
- rangeの値を適切に設定する(通常は50〜200程度)
- rayDirectionが正しい方向を向いているか確認する(playerCamera.transform.forwardを使用)
- 敵のColliderが設定されているか確認する(BoxCollider、SphereColliderなど)
失敗2:処理が重い
物理演算を使う場合、処理が重くなることがあります。
最適化を行うことで、パフォーマンスを改善できます。
解決方法:
- Raycastを使った方法を採用する(処理が軽い)
- 物理演算を使う場合は、弾の数を制限する(最大10〜20発程度)
- 不要な物理演算を無効化する(重力を無効にするなど)
- オブジェクトプールを実装する(弾の生成と破棄を最適化)
失敗3:ダメージが適用されない
ダメージが適用されない場合、Enemyコンポーネントの有無や、TakeDamage関数の実装を確認することが重要です。
⚠️ 解決方法
- Enemyコンポーネントがアタッチされているか確認する
- TakeDamage関数が正しく実装されているか確認する
- hit.collider.GetComponent<Enemy>()がnullでないか確認する
- ダメージ値が正しく設定されているか確認する
失敗4:Raycastの方向がずれる
Raycastの方向がずれる場合、カメラの向きが正しく取得できていない可能性があります。
解決方法:
- playerCamera.transform.forwardを使用して方向を取得する
- カメラの位置と向きを確認する(デバッグログで確認)
- Raycastの開始位置を確認する(playerCamera.transform.positionを使用)
- カメラが正しく設定されているか確認する
失敗5:物理演算で弾が飛ばない
物理演算を使う場合、弾が飛ばないことがあります。
⚠️ 解決方法
- Rigidbodyコンポーネントがアタッチされているか確認する
- 速度を正しく設定する(rb.velocity = transform.forward * speed)
- 重力の影響を受けないように設定する(rb.useGravity = false)
- 弾の向きが正しいか確認する(transform.forwardを使用)
初心者がよくやる勘違い
初心者がよくやる勘違いとして、物理演算を使わないとリアルな弾を作れないと思い込むことがあります。
Raycastを使った方法でも、十分にリアルな弾システムを実装できます。
また、Raycastと物理演算を同時に使おうとする場合もあります。
通常は、どちらか一方を使うことで、十分な機能を実現できます。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
実用的な弾システム完成までの4ステップ

- STEP1Raycastの実装(所要1時間)
基本的なRaycast処理を実装する。
カメラの位置から前方にRaycastを発射し、当たり判定を行う。
学べること:Raycast、当たり判定、Physics.Raycastの使い方
成果物:基本的なヒット判定システム、Raycastによる当たり判定
- STEP2ヒット判定の追加(所要1時間)
当たった対象を判定し、ダメージを与える処理を追加する。
Enemyコンポーネントを取得して、TakeDamage関数を呼び出す。
学べること:ヒット判定、ダメージ処理、GetComponentの使い方
成果物:ダメージを与えられるシステム、敵のHP管理
- STEP3物理演算の追加(所要2時間)
必要に応じて、物理演算を使った弾を追加する。
Rigidbodyコンポーネントを使って、リアルな弾の飛翔を実装する。
学べること:物理演算、Rigidbody、OnTriggerEnter
成果物:リアルな弾の飛翔が実装されたシステム、物理演算による当たり判定
- STEP4最適化と調整(所要1時間)
処理負荷を確認し、必要に応じて最適化する。
パフォーマンスを測定して、問題があれば修正する。
学べること:パフォーマンス最適化、バランス調整、プロファイリング
成果物:実用的な弾システム、最適化された処理
合計5時間で、実用的な弾システムが完成します。
実装時のチェックリスト
✅ 実装時のチェックリスト
- Raycastの実装が正しく動作しているか
- enemyLayerが正しく設定されているか
- rangeの値が適切か
- Enemyコンポーネントが正しく実装されているか
- ダメージ処理が正しく動作しているか
- 物理演算を使う場合は、パフォーマンスに問題がないか
- 弾の数が適切か(物理演算の場合)
- テストプレイで問題がないか
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
まとめ

FPSの弾の当たり判定は、Raycastを使うことで実現できます。
Unityを使えば、初心者でもヒット判定システムを作ることができるでしょう。
✅ 記事の要点まとめ
-
- 弾の当たり判定の仕組み:Raycastと物理演算の使い分け、Raycastは瞬間的な当たり判定、物理演算はリアルな弾の飛翔
- Raycast実装:瞬間的な当たり判定の実装方法、Physics.Raycastの使い方、enemyLayerの設定、散弾処理の実装
物理演算:リアルな弾の飛翔処理、Rigidbodyコンポーネントの使い方、物理演算の最適化
- ヒット判定とダメージ処理:当たった対象の判定とダメージ処理、部位によるダメージの違い、ダメージ処理の実装
- よくある失敗5選:弾が当たらない、処理が重い、ダメージが適用されない、Raycastの方向がずれる、物理演算で弾が飛ばない
- 実用的なシステム:4ステップで完成(合計5時間)
今日から始める3ステップ:
- STEP1:Raycastの実装(所要1時間)
- STEP2:ヒット判定の追加(所要1時間)
- STEP3:ダメージ処理の実装(所要30分)
あなたのペースで、少しずつ進めていけば大丈夫です。
Unity入門の森を見る 初心者歓迎!動画×プロジェクト一式で本格ゲーム制作を学べる



コメント