自作ゲームリメイク中-当たり判定・弾丸編-(Unity制作)
前回>自作ゲームリメイク中-ステータスとuGUIの連携編-(Unity制作) - Redhuのゲーム開発Fragments
前回からだいぶ時間が開いてしまいましが、動画のほうで進捗をあげてみました。
まずぱっと見で分かる変化。APの数値表示とENの残り%を表示するようにして、ゲージはそれぞれ1/4円表示にしました。開いてる下の円形部分は後々、左右武器のリロードタイム表示に使ったりなんかしようかと。
攻撃力を持つ弾丸、及びそれを飛ばしてくるオブジェクトをテストめいて配置しました。自機には当たり判定を実装。受けた弾丸の攻撃力と部位の防御力でダメージを算出する仕組みを入れました。
他にもエフェクトやサウンドとか色々やってますが、今回はこの、弾丸と当たり判定中心の記事です。
被弾側の当たり判定
BoxColliderを、ボーンオブジェクトにつけて大雑把に当たり判定が取れるように形作ります。
当たり判定をつけたボーンオブジェクトのTagとLayerをそれぞれ、Parts,Unitと新しくつくって付けます。弾丸が当たる対象を決めるための判定に使います。
実際に防御力とダメージを処理するのは根本のオブジェクトのParts_ArmorStatsです。弾丸から渡された威力を受け取り、自身の防御力でダメージを算出し、親であるPlayerオブジェクトのAP現在値を減少させます。
APを管理するのはUnitAPスクリプトとして独立させました。
子のParts_ArmorStatsと合わせて雑魚敵とかにも流用できるかなーって。
今回作っているゲームでは、攻撃力・防御力ともに「貫通」「衝撃」「熱量」の三属性を常に持ちます。受けたそれぞれの攻撃値をそれぞれの防御値で減衰した合計がダメージとなります。
弾丸の当たり判定
結論からいうと、Collider(isTriggerで)を使うもののOnTriggerEnterとかは使わないちょっと特殊な判定をやってます。
理由としましては、通常のその方法だと弾速が速くなった場合に(Collision DetectionをContinuousにしようとも)物体を貫通してしまう自体が頻発したためです。
ついでに複数のパーツが隣接する場所に弾丸が当たった場合、1発の弾丸に複数部位が反応して多重ダメージを受けてしまうこともありました。
貫通防止したくてCollisionのサイズを大きくすると多重ヒットが発生する・・・
その解決策として
DontGoThroughThings - Unify Community Wiki
このスクリプトをお借りして少々改良を加えたものを使っています。
要するにrigidbodyの移動分Rayを飛ばして、高速時の物体貫通を防止するスクリプトといえばいいんでしょうか。これを弾丸オブジェクトにつけています。
コンポーネントとしてオブジェクトにつけると、Rayが感知するオブジェクトのLayer設定が項目が見えるので感知対象にさっきつくったUnitレイヤーを設定してあげます。
独自改造として、同じ弾丸オブジェクト内の弾丸スクリプト(BulletScript)を取得しておいて、Rayの当たり判定時に
BulletScript.TriggerEnter(hitInfo.Collider);
として、弾丸が何かに当たった時の処理を起動しています。
弾丸スクリプト
長いですが
publicなところは要するに
- 自動消滅時エフェクト、ヒット時エフェクト
- 貫通、衝撃、熱量攻撃力
- 姿勢影響力を設定(防御側で未使用の項目)
- 弾丸の速度
- 弾道のバラけ度
- 攻撃力が100%発揮される有効射程
- 有効射程以上飛んだ時の威力減衰度
- 弾丸のTrailエフェクト
ッて感じです(Listをpublicにする必要はあったのだろうか
弾丸が生成された瞬間、バラけ角度分だけランダムに向きを変え、弾速分の力をrigidbodyに加えてふっ飛ばしてます。有効射程を超えるまで重力の影響は受けず真っ直ぐ飛んできます。
発射音、着弾音はそれぞれ、発射するオブジェクト、ヒット時エフェクトが発生させるので弾丸では扱いません。
ヒット時エフェクトは、着弾判定が行われた場所ではなく、着弾対象となったオブジェクトの部位で発生させています(発生を判定場所にすると、貫通補正の判定時に貫通していた先でエフェクトが発生して違和感あるため)
あとは大体中のコメントに書いてあることをしているだけ。
ちょっとした工夫で、弾丸のTrailエフェクトを弾丸オブジェクトの子として持っておいて弾丸が消える直前に切り離しています。そうしないとTrailのエフェクトが着弾時に一気に消えるので、なんとなく違和感が出ます。
弾丸の攻撃力を伝えるためにSendMessageUpwardsを使っているのは、着弾箇所はあくまでパーツの部位になるからです。防御力・ダメージ処理を持つスクリプトはその根本のパーツになるためUpwardsで登って行ってもらってます。
(多分、親であるPlayerまでメッセージ行ってるけど対象関数持ってないからダイジョーブダイジョーブ)
弾丸と当たり判定はこんなかんじで実装しました。
色々説明不足かと思いますので何かあれば気軽にお聞きください。