Unity VFX Graph 기초와 GPU 파티클 시스템
VFX Graph는 Unity의 GPU 기반 파티클 시스템으로, 기존 Particle System(Shuriken)과 달리 연산이 GPU에서 병렬로 실행됩니다. 수십만 개의 파티클을 실시간으로 처리할 수 있으며, 노드 기반 시각 편집기로 복잡한 이펙트를 만들 수 있습니다.
요구사항: URP 또는 HDRP (Built-in 파이프라인 미지원), Compute Shader 지원 GPU
1. VFX Graph 구조
섹션 제목: “1. VFX Graph 구조”VFX Graph는 네 가지 컨텍스트로 구성됩니다.
[Spawner Context] ← 파티클 생성 타이밍/수량 제어 ↓[Initialize Context] ← 각 파티클 초기 속성 설정 ↓[Update Context] ← 매 프레임 파티클 속성 갱신 ↓[Output Context] ← 렌더링 방식 결정 (Quad, Mesh, Strip 등)2. 기본 설정
섹션 제목: “2. 기본 설정”// VFX Graph 컴포넌트 참조using UnityEngine.VFX;
public class VFXController : MonoBehaviour{ [SerializeField] private VisualEffect vfxEffect;
void Start() { // 재생 제어 vfxEffect.Play(); vfxEffect.Stop(); vfxEffect.SendEvent("OnHit"); // 이벤트 트리거
// 속성 설정 vfxEffect.SetFloat("SpawnRate", 100f); vfxEffect.SetVector3("SpawnPosition", transform.position); vfxEffect.SetTexture("MainTexture", myTexture); vfxEffect.SetGradient("ColorOverLife", gradient); vfxEffect.SetBool("Active", true); }}3. Exposed Properties (노출 속성)
섹션 제목: “3. Exposed Properties (노출 속성)”VFX Graph 에디터에서 속성을 Exposed로 설정하면 C#에서 런타임으로 제어할 수 있습니다.
public class FireEffect : MonoBehaviour{ [SerializeField] private VisualEffect fire;
// 불의 세기 조절 (0~1) public void SetIntensity(float intensity) { fire.SetFloat("SpawnRate", Mathf.Lerp(0f, 500f, intensity)); fire.SetFloat("ParticleSize", Mathf.Lerp(0.1f, 0.5f, intensity)); fire.SetFloat("Lifetime", Mathf.Lerp(0.5f, 2.0f, intensity)); fire.SetVector3("Velocity", Vector3.up * Mathf.Lerp(1f, 5f, intensity)); }
// 폭발 이벤트 public void Explode() { fire.SendEvent("Explode"); fire.SetFloat("ExplosionRadius", 5f); }}4. Event Attribute Payload
섹션 제목: “4. Event Attribute Payload”이벤트와 함께 데이터를 전달합니다.
using UnityEngine.VFX;
public class ProjectileHit : MonoBehaviour{ [SerializeField] private VisualEffect hitEffect;
private VFXEventAttribute _attr;
void Awake() { _attr = hitEffect.CreateVFXEventAttribute(); }
public void OnHit(Vector3 position, Vector3 normal, float force) { _attr.SetVector3("HitPosition", position); _attr.SetVector3("HitNormal", normal); _attr.SetFloat("Force", force);
hitEffect.SendEvent("OnHit", _attr); }}VFX Graph의 Initialize 컨텍스트에서 Get Attribute 노드로 전달된 데이터를 읽어 각 파티클 초기값으로 사용합니다.
5. Spawn System
섹션 제목: “5. Spawn System”// Spawner Context 노드 구성 예시
[Constant Burst] ← 한 번에 N개 생성 Count: 100
[Constant Rate] ← 초당 N개 지속 생성 Rate: 50
[Periodic Burst] ← 주기적으로 N개 생성 Count: 20, Period: 0.5s6. Custom HLSL 블록
섹션 제목: “6. Custom HLSL 블록”VFX Graph에서 커스텀 HLSL 코드를 삽입합니다.
// VFX Graph의 Custom HLSL 노드에 입력void NoisyVelocity( inout float3 velocity, in float3 position, in float time, in float scale, in float strength){ float3 noisePos = position * scale + time * 0.5; float3 noise = float3( sin(noisePos.x * 1.7 + noisePos.z * 2.3), cos(noisePos.y * 1.3 + noisePos.x * 1.9), sin(noisePos.z * 2.1 + noisePos.y * 1.5) ); velocity += noise * strength;}7. C# → VFX Graph 위치 동기화
섹션 제목: “7. C# → VFX Graph 위치 동기화”public class TrailEffect : MonoBehaviour{ [SerializeField] private VisualEffect trailVFX;
private Vector3 _lastPosition;
void Update() { // 이동 속도를 VFX에 전달 Vector3 velocity = (transform.position - _lastPosition) / Time.deltaTime; _lastPosition = transform.position;
trailVFX.SetVector3("Position", transform.position); trailVFX.SetVector3("Velocity", velocity); trailVFX.SetFloat("Speed", velocity.magnitude);
// 빠를 때만 이펙트 활성화 trailVFX.SetBool("Active", velocity.magnitude > 5f); }}8. Texture와 Flipbook
섹션 제목: “8. Texture와 Flipbook”// Flipbook 애니메이션 텍스처 설정public class FlipbookEffect : MonoBehaviour{ [SerializeField] private VisualEffect vfx; [SerializeField] private Texture2D flipbookTexture; // 8x8 시트
void Start() { vfx.SetTexture("FlipbookTexture", flipbookTexture); vfx.SetVector2("FlipbookSize", new Vector2(8, 8)); vfx.SetFloat("AnimationSpeed", 24f); // 초당 24프레임 }}9. 성능 최적화
섹션 제목: “9. 성능 최적화”// 카메라 거리에 따른 LODpublic class VFXLODController : MonoBehaviour{ [SerializeField] private VisualEffect vfx; [SerializeField] private Camera mainCamera;
[Header("LOD 거리")] [SerializeField] private float highQualityDist = 10f; [SerializeField] private float mediumQualityDist = 30f;
void Update() { float dist = Vector3.Distance( transform.position, mainCamera.transform.position);
if (dist < highQualityDist) { vfx.SetFloat("SpawnRate", 500f); vfx.SetFloat("MaxParticles", 10000f); } else if (dist < mediumQualityDist) { vfx.SetFloat("SpawnRate", 100f); vfx.SetFloat("MaxParticles", 2000f); } else { vfx.SetFloat("SpawnRate", 0f); // 생성 중단 } }}10. 주요 Output 컨텍스트 종류
섹션 제목: “10. 주요 Output 컨텍스트 종류”| Output 타입 | 용도 |
|---|---|
| Output Particle Quad | 빌보드 스프라이트 (가장 일반적) |
| Output Particle Mesh | 3D 메시 파티클 |
| Output Particle Strip | 리본/트레일 |
| Output Particle Point | 포인트 클라우드 |
| Output Particle Lit Quad | 조명 영향 받는 스프라이트 |
- VFX Graph = GPU Compute Shader 기반 → 수십만 파티클 가능
- Spawner → Initialize → Update → Output 4단계 파이프라인
VisualEffect.SetFloat/Vector3/Bool등으로 C#에서 실시간 제어SendEvent()로 이벤트 트리거,VFXEventAttribute로 데이터 전달- HDRP/URP 전용 — Built-in 렌더 파이프라인 미지원