イラスト、モデリング、Unity、VR関連

unityとかblenderとかvr関連の作業メモ

unity パーティクルをスクリプトから弄る場合

++基本

ParticleSystemはParticleSystemコンポーネントから操作する。

ParticleSystemから放出されたParticleはGetParticlesで取得する。

ParticleSystem ps = gameObject.GetComponent<ParticleSystem>();
ParticleSystem.Particle[] ps_m = new ParticleSystem.Particle[ps.main.maxParticles];
int p_num = ps.GetParticles(ps_m);

 GetParticlesは第一引数に渡されたParticle[]型の変数にParticleのデータを入れる。

SetParticlesに操作後のデータを入れて更新する

ps.SetParticles(ps_m,p_num);    

 

++各パーティクルのライフタイムをゼロにするコード

ParticleSystem ps = gameObject.GetComponent<ParticleSystem>();
ParticleSystem.Particle[] ps_m = new ParticleSystem.Particle[ps.main.maxParticles];
int p_num = ps.GetParticles(ps_m);
for(int i = 0;i < p_num;i++){
  ps_m[i].remainingLifetime = 0;
}
ps.SetParticles(ps_m,p_num);

++公式ドキュメント

ParticleSystem - Unity スクリプトリファレンス

Particle - Unity スクリプトリファレンス

 

++一つ一つのパーティクルで処理をトリガーしたい場合

Send Collision Messagesにチェックを入れると、OnParticleCollisionメソッドがコールバックされるので、そこに処理を書き込んでいく感じ。

Unityのパーティクルの粒子1つ1つの衝突をスクリプトで検知する | Unityを使った3Dゲームの作り方(かめくめ)

 

パーティクルの衝突相手についての処理をしたい場合はOnParticleCollisonを使う

MonoBehaviour.OnParticleCollision(GameObject) - Unity スクリプトリファレンス

衝突したパーティクル自身の処理をしたい場合はOnParticleTriggerを使う

Triggers モジュール - Unity マニュアル

 

OnParticleTriggerを使うにはTriggerモジュールでイベントをcallbackに設定し、衝突させたいオブジェクトをcollidersの項目に設定する必要がある

 

++SubEmitterの回転

SubEmitterから放出されたパーティクルは放出元オブジェクトの回転を引き継がないっぽい。パーティクルが回転しない場合はSubEmitterから放出してないか疑うべき

 

++衝突相手のオブジェクトによって処理を変える方法

パーティクルと通常オブジェクト間では現状では出来ないと考えるべき。

trigger判定で処理を分岐させたいような場合は、MeshRendererをオフにした普通の球体オブジェクト等に、その子要素としてsimulation spaceをlocalにしてspeedを0にしたパーティクルを置く。これでオブジェクトを移動させればパーティクルも一緒に移動するので、通常通りOnTriggerEnterで判定を行えばよい。

 言い換えれば、パーティクルは飽くまでエフェクトとして扱い、判定はオブジェクトに任せるやり方

 

パーティクルのみでやるにはOnParticleTrigger内で衝突相手のオブジェクトを取得出来るようになる必要がある。今後の実装に期待したい

OnParticleCollision内ならGetTriggerParticlesで衝突したパーティクルを取得出来ないこともないが精度にやや難がある。collsionのコールバックでtriggerしたパーティクルを取得するのだからそもそも不整合でもある。加えてcollisionなので物理演算が必須でありtriggerのような当たり判定のみを行うことが出来ない。

+一応やり方は書いておく

 collisionとtriggerの両方をオンにする。

triggerのオンはGetTriggerParticlesを使うのにいる

f:id:arumogina:20190321094740p:plain

  void OnParticleCollision(GameObject obj){
    Debug.Log("Collision");
    ParticleSystem ps = GetComponent();
    // particles
    List enter = new List();
    // get
    int numEnter = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, enter);
    Color32 color = new Color32(0, 0, 255, 255);
    switch(obj.tag){
      case "apple":
        color = new Color32(255, 0, 0, 255);
      break;
      case "banana":
        color = new Color32(0, 255, 0, 255);
      break;
    }
    for (int i = 0; i < numEnter; i++){
        ParticleSystem.Particle p = enter[i];
        p.startColor = color;
        enter[i] = p;
    }
    ps.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, enter);
  }

 

++パーティクル同士のcollision,trigger判定

現状では無理。上にも書いたように通常オブジェクト以下にパーティクルを配置し、そのオブジェクト間で判定する。