当たり判定の基本と種類、流れの説明

概要

最終更新日:2020/03/03

ゲームの主要処理である当たり判定について書いた記事です。
この記事は以下の内容を知りたい方に向けて書いています。
  • 当たり判定とは何かを知りたい
  • 判定の種類を知りたい
  • 判定の流れを知りたい
  • 最適化について知りたい



当たり判定とは

当たり判定とはゲーム内のオブジェクト同士が当たっている(重なり、衝突等)か
どうかを判定する処理の総称です。
判定に使用するゲームオブジェクトはプレイヤーや敵、ステージだけではなく、
カメラやライトなど様々なオブジェクトが対象となります。
ほとんどのゲームで当たり判定は実装されており、
「描画」「入力」「音」のゲームの基本要素と同レベルで必須とされる機能です。

collision_0002

上の絵では次フレームに弾と敵オブジェクトの当たり判定で当たっていると判定され、
弾が消えたり、敵が爆発したりします。

判定の種類

判定には様々な種類があります。
※各判定については記事を書いたらリンクを張ります。

判定の種類
種類 説明
点と円 点と円の当たり判定を行います。
円と円 円と円の当たり判定を行います。
円と線分 円と線分の当たり判定を行います。
扇形(円弧)と点 扇(円弧)と点の当たり判定を行います。
点と矩形 点と矩形の当たり判定を行います。
点と回転した矩形 点と回転した矩形の当たり判定を行います。
矩形と矩形 矩形と矩形の当たり判定を行います。
矩形とマップチップ 矩形とマップチップの当たり判定を行います。
回転した矩形と矩形 回転した矩形と矩形の当たり判定を行います。
矩形と円 矩形と円の当たり判定を行います。
回転有りの矩形と円 回転した矩形と円の当たり判定を行います。
線分と線分 線分と線分の当たり判定を行います。
矩形と線分 矩形と線分の当たり判定を行います。
矩形と円 矩形と円の当たり判定を行います。
球と球 球と球の当たり判定を行います。
立方体と立方体 立方体と立方体の当たり判定を行います。
回転した立方体と立方体 回転した立方体と立方体の当たり判定を行います。
球と立方体 球と立方体の当たり判定を行います。
球と線 球と線の当たり判定を行います。
立方体と線 立方体と線の当たり判定を行います。
カプセルとカプセル カプセルとカプセルの当たり判定を行います。

判定結果の情報

当たり判定で必ず必要な結果情報は「当たっているか」「当たっていないか」です。
そのため、当たり判定の関数では戻り値をbool型にしているケースが多いです。

bool OnCollision(オブジェクト1, オブジェクト2)
{
	if (オブジェクト1とオブジェクト2が当たっている)
	{
		return true;
	}
	return false;
}


その他に、当たった相手や当たった位置、距離等の情報がいる時も
ありますが、ゲームや当たりの仕様によって情報は異なるので、
必要に応じて追加します。

判定の流れ

collision_0001

上のフローは当たり判定の流れの例の1つです。

①.判定用データの準備

判定を行うオブジェクトを用意します。
当たり判定は基本的に2つのオブジェクトで行うので、
データは2つ用意して下さい。

②.判定

判定は①のデータに対して当たっているかどうかを判定します。
この判定で使用する方法は「判定の種類」で紹介している方法を使用します。
判定の結果、当たっていると判定されたら③へ進み、
当たっていなければ判定に関する処理は終了です。

③.相手情報の通知

当たっていた場合は、移動を制限したり、描画をとめたり、
パラメータを変更したりと様々な対応を行う必要があります。
そのためには「誰と当たったか」「どこで当たったたか」などの
情報が必要になることがあるので、当たりと判断されたら、
それらの情報を各データに渡します。

④.当たりの対応

誰と当たったかなどの情報から当たったあとの対応を行います。
ここで移動の制限やHP、残機などの減少処理などを実装します。

注意点

今回紹介している当たり判定のフローは数あるフローの中の1つです。
全てのゲームがこのフローにより当たり判定を実装しているわけではありません。

例えばプレイヤーオブジェクトに敵との当たり判定や
ステージとの当たり判定の関数を実装したり、
④の当たりの対応を次フレームのゲーム処理にまわすこともあります。

最適な方法はゲームによって異なるので、今回のフローは
参考程度に考えてください。
通知情報のデータもあくまで例として書いています。
実際に必要な情報はゲームによって変わります。

最適化について

当たり判定は詳細な判定を求めれば求めるほど、処理コストが上昇します。
その結果、パフォーマンスが低下し、ゲームとして満足に動作しなくなります。
当たり判定はある程度の妥協と判定の最適化が必須になります。

最適化

当たり判定を行う上で判定の最適化は必須です。
最も効果的な方法のひとつとして「判定を行わない」が考えられます。
その他に「判定方法を変更する」「処理コストの低い判定を先に行う」などがあります。

判定を行わない

当たり前の話ですが、判定処理が重いなら判定処理を行わないことが
一番の最適化につながります。
判定処理を見てみて必要のない判定を行っていないかを確認して下さい。
もし、意味のない判定が行われていたらその判定処理を行わないように
することが最適化につながります。
		
例①:
	シューティングで相殺するわけでもないのに
	自機の弾と相手の弾で判定を行っている

例②:
	非アクティブ(非描画)状態のオブジェクトが判定に含まれている

判定方法を変更する

当たり判定は常に詳細な判定を取る必要はありません。
3Dゲームでプレイヤーと敵、敵と敵などに使用する判定は
ポリゴン1つ1つに対して判定を取る細かい判定ではなく、
立方体と立方体など、処理コストの低い判定を使用しても
十分にゲームとして成り立ちます。

処理コストの低い判定を先に行う

どうしても処理コストの高い判定を行う必要がある場合は
先に円や球などの処理コストが低い判定処理を行い、
そちらの判定に当てはまる場合のみ、コストの高い処理をします。