這一篇來講講粒子怎麼控制,在 Unity 的粒子系統裡,其實每一顆粒子都可以被手動控制,這裡我們做一個範例來看看。
在這個例子,我們手動把粒子設定在我們要的位置,最簡單就是把它排成一個的正方體。然後再給它一個隨機的方向速度,讓它噴出去。
設定
以下是我們對粒子系統的設定:
- PlayOnAwake 是關閉的。
- Collision 是打開的讓它有碰撞。
- Renderer 把它設定成 Mesh Cube,因為我們會對粒子改顏色,所以建立一個 Material 再寫一個簡單有頂點色的 Shader 給 Renderer。
除了以上三個,其它功能的都是關閉不勾選的。
操作流程
我們操作粒子的流程如下:
- ParticleSystem.MainModule.maxParticles 設定粒子的最大噴發數
- ParticleSystem.Emit 噴發粒子
- ParticleSystem.GetParticles 取出所有可用粒子
- ParticleSystem.Particle.position 設定粒子位置
- ParticleSystem.Particle.startSize 設定粒子大小
- ParticleSystem.Particle.startColor 設定粒子顏色
- ParticleSystem.Particle.startLifetime 設定定子存活時間
- ParticleSystem.SetParticles 把設定過的粒子塡回粒子系
要注意的是 ParticleSystem.GetParticles 時,傳進去的 Array 必需要先 new 出來,不然會取不到粒子的 array。
按鍵輸入
為了能看清楚粒子排出來的結果,我們寫成按下 A 鍵時會建立粒子並把 ParticleSystem.MainModule.simulationSpeed 設為 0 讓它停留在原位;然後按下 B 鍵時再手動把 simulationSpeed 設 1 讓它模擬下去,爆炸開來。
大約就這樣子,簡簡單的就完成了!
我們也可以在 LateUpdate 每個 frame 對粒子各種變化的操作,如對位置的運算加入數學公式,粒子就會依公式的結果顯示在結果的位置。
以下就是程式及 Shader
CS:
//Arc https://arclee0117.wordpress.com using System.Collections; using System.Collections.Generic; using UnityEngine; public class ParticleExp : MonoBehaviour { public ParticleSystem m_ParticleSystem; ParticleSystem.Particle[] m_Particles; public uint m_DimX = 1; public uint m_DimY = 1; public uint m_DimZ = 1; public float m_Size = 1; public float m_ForceScale = 1; bool m_CreateParticle = false; // Use this for initialization void Start () { } void Update() { if (Input.GetKeyUp(KeyCode.B)) { // 開始。 ParticleSystem.MainModule mm = m_ParticleSystem.main; mm.simulationSpeed = 1.0f; } else if (Input.GetKeyUp(KeyCode.A)) { // 設定。 SetupParticle(); } } // 把粒子設定成目標的型狀。 void SetupParticle() { ParticleSystem.MainModule mm = m_ParticleSystem.main; // 設定數量。 mm.maxParticles = (int)(m_DimX * m_DimY * m_DimZ); // 清空,噴發。 m_ParticleSystem.Clear(); m_ParticleSystem.Emit(m_ParticleSystem.main.maxParticles); if (m_Particles == null || m_Particles.Length != m_ParticleSystem.main.maxParticles) { m_Particles = new ParticleSystem.Particle[m_ParticleSystem.main.maxParticles]; } // 取出粒子。 // 因為才剛噴發而己,所以一定都是 alive 的粒子,可以拿來操作。 m_ParticleSystem.GetParticles(m_Particles); // 接下來就假設我們要噴一個大立方體的正方型。 Vector3 tempV3 = Vector3.zero; Color tempColor = Color.black; Vector3 centerPos = Vector3.zero; centerPos.x = -m_DimX / 2; centerPos.y = -m_DimY / 2; centerPos.z = -m_DimZ / 2; for (uint x = 0; x < m_DimX; x++) { for (uint y = 0; y < m_DimY; y++) { for (uint z = 0; z < m_DimZ; z++) { uint idx = (x * m_DimY * m_DimZ) + (y * m_DimZ) + z; // 設定位置。 tempV3.x = centerPos.x + x; tempV3.y = centerPos.y + y; tempV3.z = centerPos.z + z; m_Particles[idx].position = tempV3 * m_Size; //設定顏色。 tempColor.r = (float)x / (float)m_DimX; tempColor.g = (float)y / (float)m_DimY; tempColor.b = (float)z / (float)m_DimZ; m_Particles[idx].startColor = tempColor; // 設定大小。 m_Particles[idx].startSize = m_Size; // 噴出的方向。 tempV3.x = Random.Range(-1.0f, 1.0f); tempV3.y = Random.Range(-1.0f, 1.0f); tempV3.z = Random.Range(-1.0f, 1.0f); m_Particles[idx].velocity = tempV3 * m_ForceScale; m_Particles[idx].startLifetime = 10; } } } // 把改過的粒子設定回粒子系統裡。 m_ParticleSystem.SetParticles(m_Particles, m_Particles.Length); // 先停止,等一下再手動操作。 mm.simulationSpeed = 0; } }
Shader:
//Arc https://arclee0117.wordpress.com Shader "Custom/meshshader" { SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows vertex:vert // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float3 vertColor; }; struct InOutData { float4 vertex : POSITION; // The vertex position in model space. float3 normal : NORMAL; // The vertex normal in model space. float4 color : COLOR; // Per-vertex color }; void vert(inout InOutData v, out Input o) { UNITY_INITIALIZE_OUTPUT(Input, o); o.vertColor = v.color; } void surf (Input IN, inout SurfaceOutputStandard o) { o.Albedo = IN.vertColor;; } ENDCG } FallBack "Diffuse" }
不要吐草我:"霹靂星球應該不是方型的吧!"
您好! 非常棒的學習例子,請問可以跟您要整個project嗎? 純學校研究 絕不公開!
謝謝!
讚讚
謝謝支持,目前無法提供整個 Project 耶(因為整個 Project 包涵太多不可告人的東西了,要花點間間整理過才能提供最小的 Porject)。
讚讚