今回はUnityでの3Dゲーム開発に関する話題で、タイトルの通り
敵キャラクターに複雑な当たり判定をつける方法
をご紹介するという内容になっております。
Unityで3DアクションゲームやFPSなどを作っていると、特に大きな敵キャラクターの当たり判定の設定で悩むことがあります。具体的に言うと大きな敵キャラクターにおいては小さいキャラクターよりも複雑な当たり判定が必要になるのですが、それをUnity上でどうやって実現すればいいのか?という点がちょっとわかりづらいのです。
そこでここでは敵キャラクターに複雑な当たり判定を設定することで、プレイヤーの攻撃がより正確にヒットするようになる方法を具体的にご紹介しますね。
前提:なぜ大きな敵キャラクターで「より複雑な当たり判定」が必要になるのか?
はじめに前提として「なぜ大きな敵キャラクターには複雑な当たり判定が必要なのか?」という点を整理しておきましょう。
プレイヤーに近いサイズの敵の当たり判定はシンプルでOK
まず、アクションゲームやFPSなどではプレイヤーの攻撃をヒットさせるために敵キャラクターに当たり判定を設定しますよね。この当たり判定は通常、下記の画像のようにキャラクターの形に近いカプセル状のものを1つだけ設定することが多いです。
なぜこのような「カプセル状の当たり判定を1つだけ」使うのかというと主に次のような理由があります。
- 敵の当たり判定は大雑把な形状でよいから(複雑にすると余計な負荷がかかってしまう)
- カプセルだと人型の敵に近い形状で違和感が少なく、しかもプレイヤーや障害物に引っかかりにくいから
まあ要するに処理負荷やプレイのしやすさを考えたとき、たいていはカプセル状の当たり判定を1つ使うのが一番都合がよいということです。
ただし大きな敵の場合は…
ところが例外として、この「カプセル1つだけの当たり判定」だと都合が悪くなってしまう場合があります。それが敵のサイズがプレイヤーよりもかなり大きい場合です。
この場合、下記の画像のとおりカプセル1つの当たり判定だとキャラクターの見た目と当たり判定の範囲の違いがかなり目立ってしまい違和感があります。
また、例えばその敵キャラクターが静止していればまだマシなのですが、アニメーションの関係で原点から大きく動いたりすると当たり判定がキャラクターの見た目とは全然違う場所にあることになってしまい、 プレイヤーからしたら「攻撃を当てたはずなのに当たらない」とか「攻撃を外したと思ったら当たった」というような妙なことになってしまうのです。
このような状況はゲームの手触りを確実に悪くするためできることなら回避したいものです。
敵キャラクターに複雑な当たり判定をつける方法
ではどうすればUnityで
- 敵キャラクターにある程度複雑な当たり判定を設定し
- それでいて処理負荷も現実的な範囲内に収める
ということができるでしょうか?先に結論を言ってしまうと
キャラクターのボーンに当たり判定を仕込む
のが一番現実的で楽なやり方です。一体どういうやり方なのかを具体的に見ていきましょう。
キャラクターのボーンに当たり判定を仕込む方法
まず、下記のサンプル画像をご覧ください。緑色の線で描画されている部分がキャラクターの当たり判定です。
複数の当たり判定を適当なボーンに仕込むことで、カプセル1つの当たり判定よりも複雑かつ見た目通りの当たり判定を設定することができます。また、各々の当たり判定はシンプルな形状(=プリミティブコライダー)なので処理負荷も大したことはないです。設定には多少手間がかかりますがこれが一番やりやすい方法でしょう。
作業方法は簡単です。キャラクターの適当なボーンのゲームオブジェクトの子として新しいゲームオブジェクトを作り、そこにコライダーとKinematicなRigidbodyをアタッチしてサイズや回転などを調整するだけです(※Rigidbodyがないと攻撃側で敵の当たり判定を検知できない場合があります。またこのとき、「isKinematic」をONにしておくことで余計な物理演算を無効化できます)。
例えば↑のキャラクターの腕部分の当たり判定の親子関係は次のようになっています。
個々の当たり判定に攻撃がヒットしたときの処理を作る
次に、コライダーを設定しただけでは攻撃がヒットしてもキャラクター本体にダメージを通知できないのでその辺の仕組みを作りましょう。
前提としてダメージ処理の作り方の基本を下記の記事で詳しくご説明していますので、まだチェックしてないよという方はそちらを先にご覧ください。
上記の記事でご紹介している「IDamageable」インターフェイスを継承した「Character」クラス(=個々のキャラクターのHPなどを管理するクラス)が既にあるとすると、当たり判定に攻撃がヒットしたときの処理としては下記のようなC#スクリプトを書けばOKです。
using UnityEngine;
public class Hitbox : MonoBehaviour, IDamageable
{
[SerializeField]
Character character;
public void Damage(int value)
{
character.Damage(value);
}
}
これを個々の当たり判定のゲームオブジェクトにアタッチしておけば、そこに攻撃がヒットしたときにキャラクター本体にダメージを与えられるようになります。
おわりに
以上、大きな敵キャラクターにおいて発生しがちな当たり判定の問題とその解決方法について書きました。当たり判定はゲームの手触りに直結する重要な要素なので、大きな敵キャラクターをゲームに登場させる場合はぜひ上記の方法を参考にしていただければと思います。
この記事がUnityでのゲーム開発のお役に立てば幸いです。