前回は遠方から一定間隔で無数の回転するCylinderが飛んでくるようにしました.今回はこのCylinderとPaddleとの当たり判定をして当たったらCylinderを消去してみましょう.当たり判定をするには衝突する2つの物体にCollider,少なくとも一方にRigidbodyの設定をするのでした.このときメソッドOnTriggerEnter(Collider other)を衝突する物体に設定するとその物体が衝突したときに自動的にこのメソッドが呼び出されるのでした.今回はPaddleとCylinderPrefabにCapsuleColliderを設定し,PaddleにはRigidbodyを設定しておきます.また衝突の影響を受けなくするために,FloorはColliderの設定を削除しておきましょう.
まずCylinderPrefabにCapsuleColliderをアタッチします.Cylinderは円筒形ですが,円筒形のColliderは選択肢に存在しないので,似た形としてCapsuleColliderを使うことにします.これは人型をしたプレイヤーキャラクターなどにも良く用いられる手法です.ProjectビューのAssetsフォルダ内でCylinderPrefabをクリックしてInspectorビューの一番下からAdd Componentをクリックして[Physics]→[CapsuleCollider]を選択します.CylinderPrefabのInspectorビューの一番下にCapsule Colliderが追加されるのでIs Triggerにチェックを入れます: 全く同様にPaddleにもCapsuleColliderをアタッチしてIs Triggerにチェックを入れます.
次はPaddleにRigidbodyをアタッチします.HierarchyビューでPaddleを選択しInspectorビューの一番下のAdd Componentから[Physics]→[Rigidbody]を選択しInspectorビューに追加されたRigidbodyの中からUse Gravityのチェックを外し,Is Kinematicのチェックを入れます: これでスクリプト以外は当たり判定の設定が完成しました.
次はスクリプトの編集をしましょう. ProjectビューのAssetsフォルダ内のPaddleControllerをダブルクリックしてスクリプトの編集を行います.次のように入力します:
using UnityEngine; public class PaddleController : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { if (Input.GetKey(KeyCode.LeftArrow) && transform.position.x > -10f) { transform.Translate(-10 * Time.deltaTime, 0f, 0f,Space.World); } if (Input.GetKey(KeyCode.RightArrow) && transform.position.x < 10f) { transform.Translate(10 * Time.deltaTime, 0f, 0f, Space.World); } if (Input.GetKey(KeyCode.UpArrow) && transform.position.y < 10f) { transform.Translate(0f,10 * Time.deltaTime, 0f, Space.World); } if (Input.GetKey(KeyCode.DownArrow) && transform.position.y > 1f) { transform.Translate(0f, -10 * Time.deltaTime, 0f, Space.World); } } private void OnTriggerEnter(Collider other) { Destroy(other.gameObject); } }
今回追加したのは
private void OnTriggerEnter(Collider other) { Destroy(other.gameObject); }
の部分です.PaddleとCylinderが衝突すると自動的にOnTriggerEnterメソッドが実行されます.ちなみにEntaerはColliderの内部に入る(Enter)ときに実行され,内部から外部に出るときはEnterではなくExitとなります.つまりOnTriggerExitメソッドが実行されます.画面外に敵が出た時にその敵を消去するときなどは画面領域にBoxColliderなどを付けておいて画面外に出たらOnTriggerExitメソッドでその敵を消去するなどの場合に重宝しますので覚えておきましょう.今回のコードではPaddleに当たるとCylinderが消滅するようになっています.スクリプトの編集が終わったらCtrl + sで保存しましょう.
パラメーターの微調整
Unityに戻りPlayボタンを押してゲームを実行しましょう.実行してみるとPaddleが手前すぎてCylinderをキャッチし損ねたかどうかの判定が目視では難しいようです.そこでMain Cameraの位置とPaddleの大きさ,それからPaddleのスクリプトを修正しましょう.この辺の微調整はなかなか一発では上手くいかないものです.上手くいくまで何度も微調整をしましょう.今回は次のように修正してみました: Main Cameraの位置: Paddleの大きさ: PaddleController:
using UnityEngine; public class PaddleController : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { if (Input.GetKey(KeyCode.LeftArrow) && transform.position.x > -20f) { transform.Translate(-20 * Time.deltaTime, 0f, 0f,Space.World); } if (Input.GetKey(KeyCode.RightArrow) && transform.position.x < 20f) { transform.Translate(20 * Time.deltaTime, 0f, 0f, Space.World); } if (Input.GetKey(KeyCode.UpArrow) && transform.position.y < 15f) { transform.Translate(0f,20 * Time.deltaTime, 0f, Space.World); } if (Input.GetKey(KeyCode.DownArrow) && transform.position.y > 2f) { transform.Translate(0f, -20 * Time.deltaTime, 0f, Space.World); } } private void OnTriggerEnter(Collider other) { Destroy(other.gameObject); } }
以上のように修正しPlayボタンを押すと上手くPaddleとの当たり判定ができていることが分かります:
次回はPaddleがCylinderをキャッチしたときにスコアが加算されるようにします.