콘텐츠로 이동

Unity Particle System 고급 제어

ParticleSystem ps;
ParticleSystem.MainModule main;
ParticleSystem.EmissionModule emission;
void Start() {
ps = GetComponent<ParticleSystem>();
main = ps.main;
emission = ps.emission;
}
public void SetIntensity(float intensity) {
// Emission Rate
emission.rateOverTime = intensity * 100f;
// Start Speed
var speed = main.startSpeed;
speed.constant = intensity * 5f;
main.startSpeed = speed;
// Start Size
var size = main.startSize;
size.constantMin = 0.1f * intensity;
size.constantMax = 0.5f * intensity;
size.mode = ParticleSystemCurveMode.TwoConstants;
main.startSize = size;
}
// 특정 위치에 특정 수 방출
var emitParams = new ParticleSystem.EmitParams();
emitParams.position = hitPoint;
emitParams.velocity = hitNormal * 3f;
emitParams.startSize = 0.2f;
emitParams.startColor = Color.red;
ps.Emit(emitParams, 10);
void Update() {
int count = ps.particleCount;
var particles = new ParticleSystem.Particle[count];
ps.GetParticles(particles);
for (int i = 0; i < count; i++) {
// 중력 방향 반전 (위로 올라가는 파티클)
if (particles[i].position.y > 5f)
particles[i].velocity *= -1f;
// 수명 절반 지나면 색상 변경
float ratio = 1f - (particles[i].remainingLifetime / particles[i].startLifetime);
particles[i].startColor = Color.Lerp(Color.yellow, Color.red, ratio);
}
ps.SetParticles(particles, count);
}

C#으로 조건에 따라 Sub-emitter를 활성화합니다.

// Sub Emitters 모듈 설정 (에디터)
// Birth → sparkEmitter
// Death → explosionEmitter
// 런타임 Sub Emitter 교체
var subEmitters = ps.subEmitters;
subEmitters.enabled = true;
subEmitters.GetSubEmitterSystem(0); // 인덱스로 접근
// ParticleSystem → Renderer → Material에서 Custom Vertex Streams 활성화
// TEXCOORD1.x → Custom1.x
var customData = ps.customData;
customData.enabled = true;
customData.SetMode(ParticleSystemCustomData.Custom1, ParticleSystemCustomDataMode.Vector);
// Curve로 수명에 따른 커스텀 값 설정
var curve = new AnimationCurve(
new Keyframe(0, 0), new Keyframe(0.5f, 1), new Keyframe(1, 0));
customData.SetVector(ParticleSystemCustomData.Custom1,
0, new ParticleSystem.MinMaxCurve(1f, curve));
// 1. Renderer Mode: Mesh → Sprite로 변경 (Draw Call 감소)
var renderer = ps.GetComponent<ParticleSystemRenderer>();
renderer.renderMode = ParticleSystemRenderMode.Billboard;
// 2. GPU Instancing 활성화
renderer.enableGPUInstancing = true;
// 3. 최대 파티클 수 제한
main.maxParticles = 500;
// 4. 화면 밖 파티클 정지
main.stopAction = ParticleSystemStopAction.Disable;
void AdjustQuality() {
int budget = QualitySettings.GetQualityLevel() switch {
0 => 200, // Low
1 => 500, // Medium
_ => 1000 // High
};
ps.main.maxParticles = budget; // maxParticles는 직접 수정 불가 — MainModule 통해서
var m = ps.main;
m.maxParticles = budget;
}
  • ps.main, ps.emission 등 구조체 캐싱 후 수정 → 다시 할당 패턴 필수
  • GetParticles / SetParticles로 살아있는 파티클 개별 수정 가능
  • Custom Vertex Streams + Shader로 파티클별 커스텀 데이터 전달
  • enableGPUInstancing 활성화로 메시 파티클 배치 렌더링
  • 플랫폼별 maxParticles 제한으로 성능 보장