VFX Forge
VFXForge.png
VFX Forge는 ECS 시스템 및 하이브리드 MonoBehaviour로부터 즉각적이고 지속적인 비주얼 이펙트(visual effects)를 구동하기 위한 Unity VFX Graph 프레임워크입니다.
이 프레임워크를 사용하면 게임플레이 코드가 관리되지 않는 데이터(unmanaged data) 형태로 VFX 요청을 제출하고, 해당 요청들을 GPU 버퍼로 일괄 처리하며, 비주얼 이펙트 인스턴스 하나당 GameObject를 생성하는 대신 등록된 소수의 VFX Graph를 통해 많은 효과 인스턴스를 렌더링할 수 있습니다.
목차 (Contents)
개요 (Overview)
VFX Forge 기능:
- 일반 GPU 버퍼 배치 처리(Generic GPU buffer batching): 인스턴스별 및 배열 데이터는
DataBuffer, ArrayDataBuffer, 그리고 TransformBuffer와 같은 GraphicsBuffer 속성을 통해 업로드됩니다. 각 이펙트마다 상용구 코드를 작성할 필요가 없습니다.
- 즉시 VFX(Instant VFX): 단일 프레임 스폰 요청입니다. 폭발, 데미지 숫자, 피격 효과 등 일회성 VFX에 유용합니다.
- 지속형 VFX(Persistent VFX): 추적되는 이펙트 인스턴스입니다. 각 스폰은
TrackedEntity 핸들을 반환하며, 이를 통해 이펙트가 활성화된 동안 확인, 업데이트 또는 제거할 수 있습니다. 불꽃, 게임플레이 능력, 상태 효과 등 제어 가능한 장기 지속 VFX에 유용합니다.
- 복합 데이터 업로드(Complex Data Upload): 즉시 및 지속형 VFX 모두 선택적 단일-이펙트 인스턴스 데이터와/또는 선택적 배열-이펙트 인스턴스 데이터를 전달할 수 있습니다. 이 데이터는 복잡한 효과를 구현하기 위해 원하는 방식으로 사용될 수 있습니다. 각 데이터 레이아웃 시나리오에 맞는 VFX 템플릿이 제공됩니다.
- ECS/GameObject 지원(ECS/GameObject Support): VFX Forge는 주로 ECS(Entity Component System)를 위해 설계되었으며, GameObject 지원이 추가되었습니다. 모든 공개 API는 ECS 및 GameObject 워크플로우 모두에서 접근 가능합니다.
- 타입 안정성(Type Safety): 근본 데이터가 모든 데이터 유형 페이로드를 허용하기 위해
byte로 표현되지만, 사용자 지정 TypeManager를 생성하여 등록된 타입만 특정 VFX에 전달되도록 보장합니다.
- 에디터 프리뷰(Editor Preview):
HybridVisualEffect는 플레이 모드에 진입하지 않고도 이펙트를 미리 볼 수 있도록 에디터 모드와 직접 통합됩니다. 사용자 지정 데이터 베이커, VFX 컨트롤을 포함한 GUI 오버레이, 심지어 VFX Asset 그래프 뷰의 VFX Control 패널과의 직접적인 통합까지 제공합니다. 이는 반복 시간을 크게 증가시켜 VFX Asset 창에서 바로 시행착오 방법을 사용할 수 있게 합니다.
- VFX 기반 DecalProjector: 내부적으로 VFX Forge를 활용하는 사용자 지정
DecalProjector입니다. ECS 및 GameObject에 적합한 제작 환경과 더 나은 배치 메커니즘을 제공하여 성능 낭비 없이 수천 개의 DecalProjector를 구동할 수 있습니다.
설치(Installation)
패키지 관리자에서 다음 패키지들을 git URL을 사용하여 추가하세요:
- FireAlt.Core: https://github.com/Fire-Aalt/com.firealt.core.git
- FireAlt.VFXForge: https://github.com/Fire-Aalt/com.firealt.vfx-forge.git
이 패키지는 일시정지(Pause) 기능이 올바르게 작동하려면 선택적(optional)으로 BovineLabs.Core 통합이 필요합니다.
참고: VFX Forge는 핵심 기능을 위해 Unity.Entities (ECS)에 의존합니다. Unity 6.7에서는 Unity.Entities가 핵심 패키지가 되겠지만, 이전 버전에서는 프로젝트에 이미 존재하지 않는 경우 VFX Forge가 이 종속성을 설치할 것입니다. VFX Forge는 ECS 지식 없이도 GameObject 워크플로우와 함께 사용할 수 있습니다.
핵심 개념 (Core Concepts)
VFXDefinition은 그래프의 ScriptableObject 식별자입니다. 이는 VFX를 설명하는 데 필요한 정보를 저장합니다.
VFXKey는 등록된 그래프 항목을 찾는 데 사용되는 런타임 핸들(runtime handle)입니다. ushort를 저장하므로, 프로젝트는 최대 ushort.MaxValue 개의 VFX 키를 가질 수 있습니다.
디칼(Decals)은 고유한 텍스처 조회마다 자체 정의를 생성하기 때문에 키를 빠르게 소모할 수 있으니, 많은 디칼이 텍스처 소스를 공유해야 하는 경우에는 스프라이트 아틀라스(sprite atlases)를 선호하는 것이 좋습니다.
VFXSingleton은 ECS 싱글톤입니다. 이는 공개 API 진입점이며, 등록된 인스턴트 및 지속적 항목을 저장하고 작업(job) 사용을 위해 AsParallelWriter()를 노출합니다.
InstantVFXEntry는 선택적 단일 데이터와 선택적 배열 데이터를 포함하는 한 프레임 스폰 요청을 받습니다.
PersistentVFXEntry는 추적되는 스폰 요청을 받고 TrackedEntity 핸들을 반환합니다. 지속적인(persistent) 핸들은 SyncVFXSystem이 이를 백킹 지속성 버퍼로 해결할 때까지 지연될 수 있습니다.
VFXTransform은 VFX Graph에 업로드되는 지속적 변형(transform) 페이로드입니다. 여기에는 위치, 회전, 크기, 추적 지속 시간 및 패킹된 활성 상태가 포함됩니다.
시작하기 (Getting Started)
단계별 설정 워크스루는 Getting Started를 참조하십시오.
인스턴트 VFX (Instant VFX)
한 프레임 스폰 요청입니다. 폭발, 데미지 숫자, 히트 효과 및 기타와 같은 즉각적인(instant) VFX에 유용합니다.
전체 API 분석 및 예시는 Instant VFX를 참조하십시오.
지속적 VFX (Persistent VFX)
명시적인 Spawn/Update/Kill API와 선택적 추적 엔티티(Entity)/게임 오브젝트(GameObject) 변환 데이터 지원을 갖춘 장기 실행 VFX입니다. Forge 저장소는 최대 용량(Max Capacity)이 활성화되지 않는 한, 정의의 초기 용량(Initial Capacity)부터 탄력적으로 증가합니다.
전체 API 분석 및 예시는 Persistent VFX를 참조하십시오.
에디터 미리보기 (Editor Preview)
HybridVisualEffect는 커스텀 인스펙터를 통해 편집 모드 초기화와 프리뷰 스폰(preview spawning)을 지원합니다. 이 인스펙터는 정의 데이터를 읽고 데이터 베이커(data bakers)를 사용하여 프리뷰 페이로드(payloads)를 스폰하거나 업데이트합니다.
HybridVisualEffect의 SceneOverlay 컨트롤 패널은 VisualEffect의 SceneOverlay 컨트롤 패널을 오버라이드하고 숨깁니다. 이 커스텀 컨트롤 패널은 모든 미리보기가 가능하도록 내부적으로 HybridVisualEffect에 직접 연결(hooks)됩니다:
VFXAsset에는 VFX Graph 패널에서 VFX를 GameObject에 "Attach to a GameObject"할 수 있는 기능이 있습니다. VFX Forge는 HybridVisualEffect에 첨부할 때 이 패널을 오버라이드하여, HybridVisualEffect와 끊김 없이 상호 작용할 수 있도록 합니다:
시스템 순서 (System Order)
런타임 그룹(Runtime groups):
| 그룹/시스템 | 순서 | 역할 |
|---|
InitializeVFXSystemGroup | LateInitializationSystemGroup | 새로운 HybridVisualEffect 인스턴스를 등록합니다. |
| ... | | |
<br>프레임 동안 VFXTransformSystem이 실행된 후, 그리고 SyncVFXSystem 이전에 영구 VFX(persistent VFX)를 스폰하지 마십시오. 만약 변환 데이터 없이 영구 스폰이 동기화(sync)에 도달하면, 해당 코드는 지속적인 VFX가 LateUpdate에서 스폰되어서는 안 된다는 구체적인 경고와 함께 오류를 발생시킵니다. | | |
병렬 안전성 (Parallel Safety)
작업(jobs) 내부에서 VFXSingleton.ParallelWriter를 사용하십시오. 이 라이터는 등록된 엔트리 조회 기능을 읽기 전용 해시 맵을 통해 노출하며, 실제 엔트리 자체는 스레드 로컬 요청 구조체를 소유합니다.
안전한 패턴:
- 병렬 작업(parallel jobs)에서
ParallelWriter.GetInstant(...).Spawn(...)를 사용하십시오.
- 병렬 작업(parallel jobs)에서
ParallelWriter.GetPersistent(...).Spawn(...)를 사용하십시오.
- 반환된 엔트리 참조를 통해 영구적인(
persistent) TrySet..., TryGet..., IsAlive, 그리고 TryKill 메서드를 사용하십시오.
- 효과가 나중에 업데이트/종료되어야 할 경우,
TrackedEntity를 어디에든 저장하십시오.
주의할 점:
- 병렬로 단일
PersistentVFXEntry에서 동일한 TrackedEntity의 영구 데이터(Persistent data)를 수정하려고 시도하지 않도록 하십시오. VFX Forge 관점에서는 이를 쉽게 확인할 방법이 없으므로, 일반적인 병렬 처리 규칙을 준수해야 합니다.
- 반환된 엔트리는 가변 참조(mutable ref)입니다. 즉각적인 작업 범위를 벗어나서 엔트리 참조를 저장하지 마십시오.
VFXTransformSystem 및 SyncVFXSystem과 관련하여 영구 스폰 타이밍 규칙을 준수하십시오.
메모리 관리 (Memory Management)
Instant 요청 버퍼는 업로드 후 재사용되고 지워집니다. 초기 용량(Initial Capacity)은 시작 할당량을 정의하며, 선택적 최대 용량(optional Max Capacity)은 동기화 업데이트 사이에서 허용되는 논리적 스폰 호출을 제한합니다.
영구 CPU 버퍼는 초기 용량으로부터 기하학적으로 성장하며 등록된 정의 수명 동안 할당량을 유지합니다. 선택적 최대 용량은 활성 핸들 및 승인 대기 핸들을 제한합니다.
영구 배열 페이로드(Persistent array payloads)는 먼저 풀링된 지연 비안전 배열(pooled deferred unsafe arrays)에 복사된 다음, 요청이 해결될 때 UnsafeHeapMemory로 이동되며, 이는 memory.alloc이 작동하는 방식과 유사합니다.
VFX Forge는 지정된 시간 동안 사용되지 않은 모든 VFX의 GPU 메모리를 할당 해제합니다. 이는 본질적으로 VFX에 대한 에셋 관리(asset management)가 필요 없이 모든 VFX를 단일 장면에 저장할 수 있게 합니다. 오직 활성화된 VFX만이 GPU 메모리를 차지하고 GPU 계산에 참여합니다. Unity 6.6을 통해 VisualEffect 컴포넌트는 자체 GPU 리소스를 완전히 할당 해제할 수 있게 되어, VFX Forge를 사용한 VFX의 GPU 메모리 관리가 매우 간단해집니다.
VFX Forge는 배치 업로드(batched uploads)와 안정적인 백킹 스토리지(backing storage)를 중심으로 설계되었으며, 가능한 모든 곳에 ECS, Bursted Jobs, 최적화된 데이터 구조를 사용합니다:
- 효과는 VFX Graph의
GraphicsBuffer 속성을 통해 업로드됩니다.
- 즉시 요청(Instant requests)은 스레드별로 수집한 후 한 번 병합하여 공유 경합(shared contention)을 방지합니다.
- 영구 항목(Persistent entries)은 가능한 경우 관련 변환/데이터 범위만 업로드합니다.
- 비활성 그래프는 타임아웃 후 비활성화되어 그래픽 버퍼를 해제하고 불필요한 그래프 업데이트를 중단합니다.
트레이드오프(Tradeoffs):
- 영구 성장(Persistent growth)은 두 배 용량의 CPU/GPU 백킹 스토리지(backing storage)를 재할당합니다. 기존에 해결된 인덱스(resolved indices)는 안정적으로 유지됩니다.
- 배열 페이로드(Array payloads)는 생성 시 복사됩니다.
- 생성 횟수(spawn counts)가 높을 때는 많은 고유 그래프 정의보다 적은 배치 정의를 선호하십시오.
제한 사항 및 피해야 할 것(Limitations and What to Avoid)
- 동일한
VFXDefinition 키를 가진 두 개의 HybridVisualEffect 인스턴스를 등록하지 마십시오.
LateUpdate 또는 VFXTransformSystem 이후이지만 SyncVFXSystem 이전의 경로에서는 영구 VFX(persistent VFX)를 생성하지 마십시오.
- 제한된 생성이 성공한다고 가정하지 마십시오: 영구 VFX에는
TrackedEntity.IsValid를, 즉시 VFX에는 부울 반환 값(boolean return value)을 확인하십시오.
- Forge 버퍼 성장은 VFX Graph 시스템의 작성된 파티클 용량(authored particle capacity)을 변경하지 않습니다. VFX Graph는 그 독립적인 컴파일 상한선(compiled ceiling)을 초과하는 오버스폰(overspawn)은 폐기합니다.
- 정의 페이로드 유형(definition payload type)과 일반
Spawn<T> 또는 TrySetUpdateData<T> 호출 간의 불일치를 만들지 마십시오.
샘플(Samples)
이 패키지에는 Unity Package Manager 샘플이 포함되어 있습니다:
Samples~/Demo/DEMO.unity: 기본 데모 씬입니다.
Samples~/Demo/DamageNumbers: 피해 숫자 그래프(damage-number graph), 데이터 타입, 글리프 베이커(glyph baker), 및 정의를 포함합니다.
Samples~/Demo/TemplatesDefinitions: 내장된 즉시형(instant)/지속형(persistent) 템플릿을 위한 정의 에셋입니다.
패키지 매니저에서 샘플을 가져와(import) 전체 그래프/데이터/정의 설정을 검사하세요.
참고: "DamageNumbersDEMO.vfx" 파일은 사용자 정의 VFX 타입(custom VFX types)을 사용하므로, 샘플을 가져온 후 수동으로 추가 재가져오기(Reimport)가 필요합니다.