前回までに作ったガンシューティングの機能で敵を攻撃する事が出来るようになりました。
が、シューティングポイントの当たっている部分が何もない空間に浮いているように見えてしまいます!
これは敵の当たり判定はCharacterControllerのコライダを使っており敵を包むような空間(大ざっぱな当たり判定)になる為、シューティングポイントはコライダの接触したポイントになってはいますが、空中に浮いているように見えてしまいます。
これでは大雑把な当たり判定のアクションゲームになってしまいますので、当たり判定個所を細かく分けて設定するようにしましょう。
どこに当たったかによって得点を変えたり、与えるダメージを変更したりすることも出来ます。
と言っても特別難しい事はしません(今までやってきた方にとっては)。
今までの機能作成の流れは以下の記事で確認出来ますので、このスクリプトは何?と思ったら確認してみてください。
体の部位によって細かく当たり判定を作る
それではやってみましょう。
敵キャラの体のそれぞれの部分にCreate Emptyで空オブジェクトを作り名前を設定します。
そしてそれぞれの部位の形にあったコライダを追加します。
↑のように手や足、胴体といったボーンの子要素に当たり判定部分を作成していきます。
コライダの位置と角度をそれぞれの部位と合わせます。
コライダはIs Triggerにチェックを入れスクリプトから使うようにし、物体としては存在しないものとします。
今回設定した敵キャラは腕はひじからよく曲がるのでひじから上と下にわけました。
ボーン自体にコライダを設定せず空のゲームオブジェクトを作ってコライダを設定した理由はボーンにコライダを設定するとコライダをうまく調整出来ない為です。
空のゲームオブジェクトにコライダを設定すれば空のゲームオブジェクトを移動や回転させて敵の部位とコライダを合わせやすくなります。
また当たり判定に使うものはすべてTagとLayerをEnemyHitに変更します。
こうすることで銃の当たり判定で
Hit名前
のそれぞれの部分が攻撃の当たり判定に使われます。
Tagを指定したのは剣で攻撃した時に当たり判定のコライダかどうかの判別に使う為です。
上のような感じで当たり判定部分を設定しました。
なんだか段ボールを使って作ったヒーローみたいになってますね・・・・。
今回はタグとレイヤーの両方でEnemyHitを作成しますが、レイヤーだけ作ってスクリプトのタグで判定している個所をレイヤーで判定するようにしても大丈夫です。
とりあえず試してみましょう
↑のようにかなり細かく当たり判定が出来るようになりました。
近接攻撃と遠距離攻撃のスクリプトを修正する
今までは敵に設定したCharacterControllerのコライダを近接攻撃、遠距離攻撃両方の当たり判定にしており、敵にはEnemyタグとEnemyレイヤーを設定していました。
しかし、今回敵の子要素に当たり判定を細かく分けた為、当たり判定の処理を変更する必要があります。
近距離攻撃のAttackSwordスクリプトを修正
剣の攻撃の当たり判定を処理しているAttackSwordスクリプトを修正します。
1 2 3 4 5 6 7 8 9 10 | void OnTriggerEnter(Collider col) { if (col.tag == "EnemyHit") { var enemyScript = col.GetComponentInParent<Enemy>(); if (enemyScript.GetState() != Enemy.EnemyState.Damage && enemyScript.GetState() != Enemy.EnemyState.Dead) { enemyScript.TakeDamage(myStatus.GetAttackPower(), col.ClosestPointOnBounds(transform.position)); } } } |
タグをEnemyからEnemyHitに変更します。
このまま実行すると剣が敵のHit系のゲームオブジェクトのコライダとの接触判定が出来ません。
CharacterControllerを取り付けたゲームオブジェクトのタグをEnemyHitにするとCharacterControllerのコライダは当たり判定が出来ます。
ここら辺は
の記事を参照してください。
接触判定が出来ないので剣のプレハブにRigidbodyを取り付けIs Kinematicにチェックを入れます。
こうすることでEnemyHitとの当たり判定をする事が出来ます。
遠距離攻撃のShotスクリプトを修正
遠距離攻撃である銃を撃った時の処理をしているShotスクリプトの当たり判定を修正します。
敵との当たり判定でEnemyレイヤーを指定していた箇所をEnemyHitに変更します(2か所?)。
1 2 3 | LayerMask.GetMask ("EnemyHit") |
次に敵のEnemyスクリプトを取得していた箇所は親のEnemyスクリプトを取得する必要があるので、
1 2 3 | hit.collider.GetComponentInParent<Enemy>().GetState() |
↑のようにGetComponentからGetComponentInParentにしてEnemyスクリプトを取得します。
今回は近接攻撃と遠距離攻撃ともにHit系ゲームオブジェクトを当たり判定の対象にしましたが、銃で細かい部位を狙う遠距離攻撃はHit系のゲームオブジェクトのコライダを当たり判定にし、剣で大雑把に攻撃する場合は敵の移動に使っているCharacterControllerのコライダを当たり判定にするというのもいいかもしれません。
キャラクターが敵に乗ってしまう場合の対処
敵のボーンに細かくコライダを設定したことで部位ごとに攻撃をすることが出来るようになりました。
ただここでひとつ問題が発生します。
それは主人公が敵のHit系のゲームオブジェクトのコライダの上に乗ってしまうことがあります。
例えばHitRightLowerFootゲームオブジェクトのコライダの角度や高さによっては主人公のCharacterControllerの設定によってはその上に乗れてしまいます。
そこでレイヤーコリジョンマトリクスを使ってEnemyHitレイヤーと主人公のPlayerレイヤーの接触をしないように設定します。
(主人公はCharacterControllerを取り付けた親だけにPlayerレイヤーを設定していることとします)。
UnityメニューのEdit→Project Settings…を選択しProject Settingsウインドウを開きます。
Physics項目を選択しLayer Collision MatrixでEnemyHitとPlayerのチェックを外します。
これで主人公が敵の上に乗る事がなくなりました。
当たり判定のコライダを増やしての感想
これで当たり判定を細かくする処理は完了です。
剣で攻撃する場合に敵の当たり判定部位と接触する度に攻撃がヒットする為、1回の剣の振りで、手、体、足の三か所に当たる可能性があります。
その為、剣の攻撃力を少し抑えた方がいいかもしれませんね。(^_^;)
ボーンの稼働域とHitコライダを設置する位置が合っているか確認するには、Unityの実行ボタンを押して、
Sceneタブに切り替え敵キャラを選択してスクリプトで歩かせてみるとわかりやすいです。
敵キャラの動きによってコライダの動きも同じように移動、回転しているかどうか確認出来るので間違いがないです。
言っている本人が確認出来ていなかったという落ちになります。(-.-)