CG・映像デザイナー技術ブログ

【Unity】パーティクルに関するエフェクト小技集まとめ[Shuriken]

eyecatch-unity-effect-particle

本記事ではパーティクルに関する小技集まとめてみました。

この記事の著者
CGブロガー すいみん

CGブロガー

すいみん

Suimin

プロフィール

某美大の油絵科を卒業後、大手CG映像プロダクションに入社。
その後ゲーム業界に転職。
現在は技術系のCGデザイナーをしています。 書籍:Unity デザイナーズ・バイブル
プロフィール詳細はこちら

パーティクルエフェクトに関する小技集まとめ

知っておくとどこかで役に立つパーティクルに関するTIPS紹介です。

uGUI(Screen Space – Overlay)の前にparticleを表示させる方法

uGUI(Screen Space – Overlay)のcanvasのSort Orderの値で、復数のcanvas(ugui)の描画順を調整することはできますが、

Screen Space – Overlay の場合はUIが必ず最前面に来るため、パーティクルを前に表示することはできません。

実用性はないのですが、レンダーテクスチャを使えば、パーティクルを前に表示できそうなので試してみました。

uGUI(Screen Space – Overlay)の上にparticleを表示する方法

Render Textureを使って描画順を調整します。

テキストとボタンの間にパーティクル(レンダーテクスチャー)を入れています。

  1. GameObject > UI >Buttonを作成
  2. ParticleDisplayerの下にGameObject > UI >RawImnageを作成。
  3. Asset > Create > Render Texture(Particle Render Texture)を作成し、RawImageにアサイン

  4. パーティクル用のカメラ(ParticleCamera)を作成

  5. Layerからparticleというレイヤーを作成して、カメラのCulling Maskをparticleに
  6. Clear FlagsをSolid Color、アルファ0に
  7. Target TextureをParticle Render Textureに

  8. ParticleCameraの子にParticle Systemを作成。※マテリアルやテスクチャもつけて好みに調整。

  9. Particle Systemのレイヤーをparticleに
  10. Textを作成して、Button,RawImage,textの階層順にする
  11. uguiのRect Transformを調整し、見た目の任意で調整。
  12. 再生、ボタンとテキストの間にパーティクルが発生するのを確認

Max Particle Sizeについて

例えば魔法陣など大きいサイズのパーティクルを出したときに、カメラをズームしても魔法陣のサイズが変わらないことがあります。

その時はMax Particle Sizeのサイズ(デフォルト0.5)の値を大きくしてやれば解決しますが、おおよその基準を調べてみました。

Max Particle Sizeのテスト1

  1. スケール10×10のPlane(赤色)を用意
  2. カメラのSizeを50にして画面に収まるように配置
  3. パーティクルを作成(黄色)Start Speedを0にして、板が表示されるように
  4. パーティクルのStart Sizeの数字を上げる。→90以上にするとサイズが変わらなくなる
  5. パーティクルのMax Particle Sizeを0.6にして、Start Sizeの数字を上げる。→Start Size100で赤いPlaneとサイズがぴったり重なる

Particle Start Size 100 = Plane Scale 10 という結果に

Max Particle Sizeのテスト2

  1. パーティクルのStart Sizeを100に固定して、カメラのSizeの値を変更しながら、赤いPlaneとサイズがぴったり重なるようにMax Particleを変更。
  2. 結果(下図)

まずはカメラがどこまでズームするかの基準を決めて、そこからパーティクルのサイズに合わせてMax Particle Sizeを入力します。

仮にカメラがSize 15までのズームするとしたら、Particle Start Size 25以上のものは、Max Particle Size デフォルトの0.5以上必要になる可能性があり、調整する必要があります。

パーティクルでテキストを発生させる方法

レンダーテクスチャを使ってます。
またテキストが変更されるとパーティクルのテキストも更新されます。

マテリアルのAssetを用意

  1. Asset Create > New Render Texture(名前はText Render)
  2. Asset Create > Material(名前はText Material)
  3. Text Materialを選択して、Mobile > Particle > Additiveに変更
  4. Text Materialを選択して、TextureにText Renderをアサイン

パーティクルのSceneの作成

  1. Main Cameraを選択して、Clear Flags > Solid Color(色は黒)
  2. Main Cameraを選択して、Ctrl+Dでカメラ(Text Camera)を複製。
  3. Text Cameraを選択して、Projection > Othographicに変更。
  4. Text Cameraを選択して、Target Textureにレンダーテクスチャ(Text Renderer)を設定
  5. Canvasを選択を選択して、Screen Space -Cameraに変更。
  6. Canvasを選択を選択して、Render CameraをText Cameraに変更。
  7. GameObject > UI > Textから文字を入力(Wow!)※Text Cameraの表示内に収める
  8. GameObject > Particle Systemを作成。
  9. Particle Systemを選択して、Render > Material > Text Materialに設定

あとはお好みでパーティクルを調整。

ちなみに数字のカウントダウンは下記のコードをテキストにアタッチ

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class TimeScript : MonoBehaviour {
private float time = 10;
void Start () {
GetComponent<Text>().text = ((int)time).ToString();
}
void Update (){
time -= Time.deltaTime;
if (time < 0) time = 0;
GetComponent<Text> ().text = ((int)time).ToString ();
}
}

パーティクルの描画が毎フレーム残り続けてしまう場合の解消方法

パーティクルの描画が毎フレーム残り続けてしまうことが起きたのですが、ちょっとしたカメラの設定が原因でした。

原因はカメラの設定がcamra > Clear Flags > Don’t Clearの場合、パーティクルの各フレームの描画が次のフレーム上に描画されてしまうようです。

真っ黒になるからと言って、よくわからない設定しまうと正しい描画の結果になりません。ということで、背景を黒くしたい時は「Solid Color」を推奨します。

パーティクルをパスに沿わせる方法

AEでは簡単にできますが、Unityではパーティクルをパスに沿わせる方法はどうやるのだろうと思って、調べて試してみました。

こちらを参考にしました。

では早速やり方を解説します。

STEP.1
動画のダウンロード先から、3点のスクリプトを入手
Math_Functions.cs
ParticlePathFlow.cs
Path_Comp.cs
STEP.2
パーティクルを作成
STEP.2
パーティクルにParticlePathFlow.csをアタッチ
STEP.2
空のGameObjectを配置
ベジェになるので、複数複製して、お好みで配置。

STEP.3
パーティクルの数字を調整して終了

Lifetime 描くスピードに影響
Size  太さに影響
Color over Lifetime 色に影響
Emission Rate 数に影響。大きすぎると1個だけ先に出てしまう。

有料アセット

参考 bezier-curved-particles-flow-editorassetstore.unity.com

パーティクルをキューブに当てて、ヒットのパーティクルを出す方法

パーティクルをキューブに当てて、ヒットのパーティクルを出す方法。
OnParticleCollisionを使用すると、パーティクル衝突時に別のパーティクルを簡単に発生させることができるが、衝突位置に発生する方法がまだシンプルではないです。

3つのゲームオブジェクトを用意”>①3つのゲームオブジェクトを用意

・A:当てる用のパーティクル(Beam)
・B:ヒット用のパーティクル(Explosion)
・障害物(ただのCube、Aが当たるように配置する)

  1. 当てる用のパーティクルのCollisionにチェック
  2. さらに設定をWorldにして、Send Collision Messagesにチェック
  3. 当てる用のパーティクルに下記のスクリプトFX_Testをアタッチ
using UnityEngine;
using System.Collections;
public class FX_Test : MonoBehaviour {
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (0)) {
GameObject go = GameObject.Find ("Beam");
go.particleSystem.Play ();
}
}
private ParticleSystem.CollisionEvent[] collisionEvents = new ParticleSystem.CollisionEvent[16];
void OnParticleCollision(GameObject other) {
GameObject hitParticle = GameObject.Find ("Explosion");
int safeLength = particleSystem.safeCollisionEventSize;
if (collisionEvents.Length < safeLength)collisionEvents = new ParticleSystem.CollisionEvent[safeLength];
int numCollisionEvents = particleSystem.GetCollisionEvents(other, collisionEvents);
int i = 0;
while (i < numCollisionEvents) {
Vector3 collisionHitLoc = collisionEvents[i].intersection;
hitParticle = Instantiate (hitParticle, collisionHitLoc, Quaternion.identity) as GameObject;
hitParticle.particleSystem.Play();
GameObject.Destroy (hitParticle, 1.0f);
i++;
}
}
}

衝突位置を割り出さない場合

void OnParticleCollision(GameObject other) {
GameObject hitParticle = GameObject.Find ("Explosion");
hitParticle = Instantiate (hitParticle, other.transform.position, other.transform.rotation) as GameObject;
hitParticle.particleSystem.Play ();
GameObject.Destroy (hitParticle, 1.0f);
}

オブジェクトが当たったらヒットエフェクトを飛ばす(OnCollisionEnter)

void OnParticleCollision(GameObject other) {
GameObject hitParticle = GameObject.Find ("Explosion");
hitParticle = Instantiate (hitParticle, other.transform.position, other.transform.rotation) as GameObject;
hitParticle.particleSystem.Play ();
GameObject.Destroy (hitParticle, 1.0f);
}

以上、すいみん(@cg_method)でした!