当たり判定
Unityのコライダーのおかげで、当たり判定は自動的に計算され、「OnCollisionXXX」「OnTriggerXXX」で衝突があった時にお知らせを受け取る、処理ができるが、実際に裏側でなにを行っているのか理解してみましょう。
球体同士
まず、一番楽なのは、球体同士の当たり判定である。以下の図を確認し、考えてみましょう
![]() |
円「C」(中心点 (cx, cy)、半径 cr )と「D」(中心点 (dx, dy)、半径 dr )があるとして、中心の間の距離は、中心の差のノルムである:
|
この距離は半径の和よりも小さければ、2つの円が衝突しているといえる。
|
|
|
つまり
|
|
練習
Unityでコライダーなしの2つの球体を作成し、MySphereCollider を作成し、半径を設定できるようにしてください(注意:コライダーの半径とメッシュの半径を合わせてください)
つぎ、SphereCollisionCheck のスクリプトを作成し
- すべての MySphereCollider を取得
- コライダー同士の距離を計算
- 半径よりも小さければ、色を変える
MySphereCollider スクリプト
// 当たり判定:球体のコライダー
public class MySphereCollider : MonoBehaviour
{
// 半径
[SerializeField]
private float radius;
// 半径を返す
public float GetRadius()
{
return radius;
}
// 色を変える
public void ChangeColor(Color color)
{
// MeshRendererの色を変える
MeshRenderer mr = GetComponent<MeshRenderer>();
mr.material.color = color;
}
}
SphereCollisionCheck スクリプト
// コライダー同士の当たり判定を確認
public class SphereCollisionCheck : MonoBehaviour
{
// すべてのコライダー
private MySphereCollider[] colliders;
private void Start()
{
// FindObjectsByType = 「このスクリプトを付いているオブジェクトのすべて下さい」
colliders = FindObjectsByType<MySphereCollider>(FindObjectsSortMode.None);
}
void Update()
{
// 初期値はすべて「false」
bool[] isCollision = new bool[colliders.Length];
// 全部 vs 全部を比較
for (int i = 0; i < colliders.Length - 1; i++)
{
for (int j = i + 1; j < colliders.Length; j++)
{
MySphereCollider iObje = colliders[i];
MySphereCollider jObje = colliders[j];
// 中心と中心の距離を計算
float distance = (iObje.transform.position - jObje.transform.position).magnitude;
// 2つの半径の足し算を計算
float radiusSum = iObje.GetRadius() + jObje.GetRadius();
// 当たり判定
if (distance - radiusSum <= 0)
{
isCollision[i] = true;
isCollision[j] = true;
}
}
}
// 衝突しているコライダーだけの色を変える
for (int i = 0; i < isCollision.Length; i++)
{
if (isCollision[i])
colliders[i].ChangeColor(Color.red);
else
colliders[i].ChangeColor(Color.white);
}
}
}
箱同士(回転なし)
BoxCollider の処理を把握しましょう。2つの箱「C」と「D」があり、それぞれが「最小X」「最大X」「最小Y」「最大Y」の数値を持っている。

この場合は:
- ある箱の「最大X」は他の箱の「最小X」よりも小さければ → 衝突しない
- ある箱の「最大Y」は他の箱の「最小Y」よりも小さければ → 衝突しない
- それ以外、衝突する
3次元の場合はZも含める。
練習
Unityでコライダーなしの2つの立方体を作成し、MyBoxCollider を作成し、幅、高さ、深さを設定できるようにしてください(注意:コライダーの半径とメッシュの半径を合わせてください)
つぎ、BoxCollisionCheck のスクリプトを作成し
- すべての MyBoxCollider を取得
- 各軸の「最大」と「最小」を比較
- 衝突したら、色を変える
MyBoxCollider スクリプト
// 箱コライダー
public class MyBoxCollider : MonoBehaviour
{
// サイズ(幅、高さ、深さ)
[SerializeField]
private Vector3 size;
// 各軸の最大位置を返す
public Vector3 GetMax()
{
return transform.position + size / 2;
}
// 各軸の最小位置を返す
public Vector3 GetMin()
{
return transform.position - size / 2;
}
// 色を変える
public void ChangeColor(Color color)
{
// MeshRendererの色を変える
MeshRenderer mr = GetComponent<MeshRenderer>();
mr.material.color = color;
}
}
BoxCollisionCheck スクリプト
// MyBoxCollider同士の当たり判定を確認
public class BoxCollisionCheck : MonoBehaviour
{
// すべてのコライダー
private MyBoxCollider[] colliders;
private void Start()
{
// FindObjectsByType = 「このスクリプトを付いているオブジェクトのすべて下さい」
colliders = FindObjectsByType<MyBoxCollider>(FindObjectsSortMode.None);
}
void Update()
{
// 初期値はすべて「false」
bool[] isCollision = new bool[colliders.Length];
// 全部 vs 全部を比較
for (int i = 0; i < colliders.Length - 1; i++)
{
for (int j = i + 1; j < colliders.Length; j++)
{
// 最大と最小位置を取得
Vector3 iMax = colliders[i].GetMax();
Vector3 iMin = colliders[i].GetMin();
Vector3 jMax = colliders[j].GetMax();
Vector3 jMin = colliders[j].GetMin();
// 軸ずつを確認
if (iMax.x < jMin.x) continue;
if (iMax.y < jMin.y) continue;
if (iMax.z < jMin.z) continue;
// 逆の比較も
if (jMax.x < iMin.x) continue;
if (jMax.y < iMin.y) continue;
if (jMax.z < iMin.z) continue;
// 当たった!
isCollision[i] = true;
isCollision[j] = true;
}
}
// 衝突しているコライダーだけの色を変える
for (int i = 0; i < isCollision.Length; i++)
{
if (isCollision[i])
colliders[i].ChangeColor(Color.red);
else
colliders[i].ChangeColor(Color.white);
}
}
}
球体と箱
SphereCollider と BoxCollider の当たり判定もあるので、その処理を学ぼう




