今回はUnityのパーティクルシステムの粒子1つ1つの衝突を検知したいと思います。
パーティクルシステム全体にコライダを設定し大ざっぱな1つのゲームオブジェクトとして衝突判定をさせるには
![](https://gametukurikata.com/wp-content/uploads/2017/03/eyecatchshockwave.png)
の記事でやりましたのでそちらを参照してください。
今回は粒子1つ1つが衝突した時に何らかの処理をしたいと思います。
ParticleSystemを作成する
衝突を検知する為のサンプルを作成していきいます。
ヒエラルキー上で右クリック→Particle Systemを選択しパーティクルを作成します。
Sceneタブで見ると↑のようなパーティクルが発生しているのが確認出来ます。
パーティクルの設定をして、パーティクルの範囲を狭めます。
↑のように設定しました。
パーティクルは↑のように発生して動いていく範囲がかなり限定されました。
次にパーティクルが衝突する相手を作成します。
StandardAssetの中のモデルEthanをヒエラルキーに配置し、CharacterControllerを取りつけコライダをモデルと合うように調整します。
↑のようにコライダのサイズを調整しました。
Ethanをパーティクルの粒子が飛んでくる場所に配置しパーティクルの衝突を確認してみます。
現在の設定では↑のようにパーティクルの衝突判定がされずコライダをすり抜けていってしまいます。
パーティクルが衝突するように設定
パーティクルが他のコライダと衝突するように設定します。
作成したParticle SystemのインスペクタでParticle Systemの設定を変更します。
Collisionの項目にチェックを入れるとパーティクルの粒子が他のコライダと衝突した時に跳ね返るようになります。
Staticなゲームオブジェクトだけでなく動くキャラクター等とも衝突させる場合はEnable Dynamic Collidersにチェックを入れておきます。
これで先ほど作成したキャラクターにパーティクルの粒子が当たって跳ね返ります。
↑のようにパーティクルがキャラクターに当たって跳ね返っているのが確認出来ます。
パーティクルの粒子が当たったのをスクリプトで検知する
次にパーティクルの粒子がキャラクターにぶつかった時にスクリプトで検知をしたいと思います。
Particle SystemのCollisionの項目でSend Collision Messagesにチェックを入れます。
そうするとParticle Systemに設定したスクリプトでOnParticleCollision関数が呼ばれるようになります。
そこでParticleCheckという名前の新しいスクリプトを作成しParticle Systemゲームオブジェクトに設定します。
1 2 3 4 5 6 7 8 9 10 11 | using UnityEngine; using System.Collections; public class ParticleCollision : MonoBehaviour { void OnParticleCollision(GameObject obj) { Debug.Log("衝突"); } } |
OnParticleCollisionではGameObject型の引数が受け取れます。
その為パーティクルが衝突した時に衝突した相手にダメージを与えたいとしたら
1 2 3 4 5 | void OnParticleCollision(GameObject obj) { obj.GetComponent<DamageScript>().Damage(attackPower); } |
等とダメージ処理をするDamageScriptスクリプトのDamageメソッドを呼び出す等すれば実現出来ます。
パーティクルの衝突をスクリプトで確認する
パーティクルが衝突したかどうかをスクリプトで確認してみます。
Particle Systemゲームオブジェクトのインスペクタは
↑のようになっています。
これで機能が完成したので、パーティクルがキャラクターに衝突した時にコンソールに『衝突』という文字列が表示されるか確認してみましょう。
↑のようにパーティクルの粒子1つ1つがキャラクターに衝突した時に『衝突』という文字列がコンソールに表示されています。
粒子1つ1つでキャラクターにダメージを与えたい時には便利ですね(^_^)v
パーティクルが主人公に当たった時に当たった場所にダメージUIを表示する
先ほどパーティクルの衝突の検知が出来る事がわかりましたので、パーティクルが衝突した時にダメージUIを表示してみたいと思います。
ダメージUIやその処理に関しては
![](https://gametukurikata.com/wp-content/uploads/img/entry_img_104.png)
で作成したものを使用します。
主人公がダメージを受けた時のスクリプトの作成
まずは主人公にParticleDamageというスクリプトを作成し取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | using UnityEngine; using System.Collections; public class ParticleDamage : MonoBehaviour { // ダメージUIプレハブ [SerializeField] private GameObject damageUI = null; // ダメージを受けた場所にダメージUIを表示 public void Damage(Vector3 pos) { Instantiate<GameObject>(damageUI, pos, Quaternion.identity); } } |
damageUIにはダメージUIのプレハブを設定します。
このスクリプト自体はダメージを受けた場所にダメージUIをインスタンス化し登場させているだけです。
ParticleCollisionスクリプトの改造
ParticleCollisionスクリプトは作成したParticleSystemに取り付けていて、衝突した時にOnParticleCollisionメソッドが呼ばれています。
個々のパーティクルが主人公のコライダのどの位置に当たったかを取得する為にParticleCollisionEventを取得し、それぞれのパーティクルの当たった位置を取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | using UnityEngine; using System.Collections; using System.Collections.Generic; public class ParticleCollision : MonoBehaviour { private ParticleSystem particle; private List<ParticleCollisionEvent> collisionEventList = new List<ParticleCollisionEvent>(); void Start() { particle = GetComponent<ParticleSystem>(); } void OnParticleCollision(GameObject obj) { if (obj.tag == "Player") { // イベントの取得 particle.GetCollisionEvents(obj, collisionEventList); // 衝突した位置を取得し、ダメージスクリプトを呼び出す foreach(var collisionEvent in collisionEventList) { Vector3 pos = collisionEvent.intersection; obj.GetComponent <ParticleDamage>().Damage (pos); } } } } |
個々のパーティクルのイベントを保持するParticleCollisionEventリストを宣言しておきます。
1 2 3 4 | // イベントの取得 particle.GetCollisionEvents(obj, collisionEventList); |
でobj(このサンプルでは主人公のゲームオブジェクト)に衝突したイベントをcollisionEventListに入れます。
イベントのintersectionでコライダとぶつかった位置を取得出来るので、ParticleDamageスクリプトのDamageメソッドを呼び出す時の引数としてその位置を渡します。
ここら辺の処理はUnityマニュアルの
を参考にさせて頂きました。
それでは実行してみましょう。
↑のようにパーティクルの粒子が当たった場所にダメージUIが表示されるようになりました。