本記事ではパーティクルに関する小技集まとめてみました。
パーティクルエフェクトに関する小技集まとめ
知っておくとどこかで役に立つパーティクルに関する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を使って描画順を調整します。
テキストとボタンの間にパーティクル(レンダーテクスチャー)を入れています。
- GameObject > UI >Buttonを作成
- ParticleDisplayerの下にGameObject > UI >RawImnageを作成。
- Asset > Create > Render Texture(Particle Render Texture)を作成し、RawImageにアサイン
-
パーティクル用のカメラ(ParticleCamera)を作成
- Layerからparticleというレイヤーを作成して、カメラのCulling Maskをparticleに
- Clear FlagsをSolid Color、アルファ0に
-
Target TextureをParticle Render Textureに
-
ParticleCameraの子にParticle Systemを作成。※マテリアルやテスクチャもつけて好みに調整。
- Particle Systemのレイヤーをparticleに
- Textを作成して、Button,RawImage,textの階層順にする
- uguiのRect Transformを調整し、見た目の任意で調整。
-
再生、ボタンとテキストの間にパーティクルが発生するのを確認
Max Particle Sizeについて
例えば魔法陣など大きいサイズのパーティクルを出したときに、カメラをズームしても魔法陣のサイズが変わらないことがあります。
その時はMax Particle Sizeのサイズ(デフォルト0.5)の値を大きくしてやれば解決しますが、おおよその基準を調べてみました。
Max Particle Sizeのテスト1
- スケール10×10のPlane(赤色)を用意
- カメラのSizeを50にして画面に収まるように配置
- パーティクルを作成(黄色)Start Speedを0にして、板が表示されるように
- パーティクルのStart Sizeの数字を上げる。→90以上にするとサイズが変わらなくなる
- パーティクルのMax Particle Sizeを0.6にして、Start Sizeの数字を上げる。→Start Size100で赤いPlaneとサイズがぴったり重なる
Particle Start Size 100 = Plane Scale 10 という結果に
Max Particle Sizeのテスト2
まずはカメラがどこまでズームするかの基準を決めて、そこからパーティクルのサイズに合わせてMax Particle Sizeを入力します。
仮にカメラがSize 15までのズームするとしたら、Particle Start Size 25以上のものは、Max Particle Size デフォルトの0.5以上必要になる可能性があり、調整する必要があります。
パーティクルでテキストを発生させる方法
レンダーテクスチャを使ってます。
またテキストが変更されるとパーティクルのテキストも更新されます。
マテリアルのAssetを用意
- Asset Create > New Render Texture(名前はText Render)
- Asset Create > Material(名前はText Material)
- Text Materialを選択して、Mobile > Particle > Additiveに変更
- Text Materialを選択して、TextureにText Renderをアサイン
パーティクルのSceneの作成
- Main Cameraを選択して、Clear Flags > Solid Color(色は黒)
- Main Cameraを選択して、Ctrl+Dでカメラ(Text Camera)を複製。
- Text Cameraを選択して、Projection > Othographicに変更。
- Text Cameraを選択して、Target Textureにレンダーテクスチャ(Text Renderer)を設定
- Canvasを選択を選択して、Screen Space -Cameraに変更。
- Canvasを選択を選択して、Render CameraをText Cameraに変更。
- GameObject > UI > Textから文字を入力(Wow!)※Text Cameraの表示内に収める
- GameObject > Particle Systemを作成。
- 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ではパーティクルをパスに沿わせる方法はどうやるのだろうと思って、調べて試してみました。
こちらを参考にしました。
では早速やり方を解説します。
[timeline]
[tl label=’STEP.1′ title=’動画のダウンロード先から、3点のスクリプトを入手’]
Math_Functions.cs ParticlePathFlow.cs Path_Comp.cs
[/tl]
[tl label=’STEP.2′ title=’パーティクルを作成’]
[/tl]
[tl label=’STEP.2′ title=’パーティクルにParticlePathFlow.csをアタッチ’]
[/tl]
[tl label=’STEP.2′ title=’空のGameObjectを配置’]
ベジェになるので、複数複製して、お好みで配置。
[/tl]
[tl label=’STEP.3′ title=’パーティクルの数字を調整して終了’]
Lifetime 描くスピードに影響
Size 太さに影響
Color over Lifetime 色に影響
Emission Rate 数に影響。大きすぎると1個だけ先に出てしまう。
[/tl]
[/timeline]
有料アセット
パーティクルをキューブに当てて、ヒットのパーティクルを出す方法
パーティクルをキューブに当てて、ヒットのパーティクルを出す方法。
OnParticleCollisionを使用すると、パーティクル衝突時に別のパーティクルを簡単に発生させることができるが、衝突位置に発生する方法がまだシンプルではないです。
3つのゲームオブジェクトを用意”>①3つのゲームオブジェクトを用意
・A:当てる用のパーティクル(Beam)
・B:ヒット用のパーティクル(Explosion)
・障害物(ただのCube、Aが当たるように配置する)
- 当てる用のパーティクルのCollisionにチェック
- さらに設定をWorldにして、Send Collision Messagesにチェック
- 当てる用のパーティクルに下記のスクリプトFX_Testをアタッチ
[open title=’コード’]
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); }
[/open]