Search Unity

Unity 비주얼 이펙트 그래프, FPS 샘플의 VFX 기능 업그레이드

, 4월 10, 2019

유니티는 작년 Unite LA에서 FPS 샘플 프로젝트와 비주얼 이펙트 그래프(Visual Effect Graph)를 공개했습니다. FPS 샘플은 개발자들에게 1인칭 슈팅 게임의 설정을 설명하기 위해 제작되었으며, 첫 번째 릴리스에서는 파티클 시스템을 사용하여 제작한 효과를 선보였습니다. 이제 파티클 시스템은 정식으로 제작에 사용할 수 있게 되었습니다. 그 다음으로 완전히 새로운 비주얼 이펙트 그래프를 사용할 수 있도록 모든 시각 효과를 업그레이드하여 결과적으로 HDRP 기능을 활용할 수 있게 되었습니다. 비주얼 이펙트 그래프가 현재 프리뷰로 제공되고 있는 상황을 감안할 때, 이와 같은 업그레이드는 정보를 수집하고 제작 패턴을 시험해 봄으로써 툴을 정식 버전으로 발전시킬 수 있게 하는 매우 의미 있는 기회였습니다. 이제 업그레이드된 기능에 대해 검토해보고, 이번 업그레이드를 통해 얻을 수 있었던 점에 대해 살펴보겠습니다.

간편해진 시스템 전환

비주얼 이펙트 그래프는 템플릿에서 효과를 실행하는 간단한 컴포넌트로 구성된 패키지로, 모든 데이터를 씬 컴포넌트로 임베드하는 파티클 시스템 솔루션과는 매우 다릅니다. 또한, 비주얼 이펙트 그래프를 사용하면 하나의 이펙트 그래프에 컴포넌트를 여러 개 포함시킬 수 있으므로 Unity에서는 여러 파티클 시스템을 렌더링하는 데 컴포넌트 하나만 사용하면 됩니다.

이러한 차이에도 유니티가 제작한 비주얼 이펙트 그래프의 C# 인터페이스가 파티클 시스템에서 사용하는 인터페이스와 매우 유사하기 때문에 동작이 매우 비슷하고 시스템 간 업그레이드도 수월한 편입니다.

FPS 샘플의 경우 다음과 같은 특징 덕분에 새 시스템으로 매우 쉽게 전환할 수 있었습니다.

  • C# 코드 상 파티클 시스템에 대한 레퍼런스가 매우 적음(거의 없음)
  • (거의) 동일한 C# 컴포넌트 API
  • 간단한 게임 코드 구조 – 추가 최적화가 용이함

유니티는 네이티브 수준에서 프리팹과 코드에서 파티클 시스템에 대한 모든 레퍼런스를 찾는 방식으로 비주얼 이펙트 그래프로의 전환을 시작했고, 그 이후에는 모든 인스턴스를 플레이스홀더로 교체했습니다. 모든 게임플레이 효과가 Assets/Effects 계층에 있는 전용 프로젝트 폴더에 저장되어 있었으므로 매우 쉬운 작업이었습니다.

씬의 다른 모든 효과는 계층 필터(hierarchy filter)를 사용하여 쉽게 식별할 수 있었습니다. 대부분의 효과가 프리팹에 저장되어 있었기 때문에 플레이스홀더로 교체하기도 매우 쉬웠습니다.

교체한 후에 효과 측면에서 개선이나 반복 작업이 필요한 경우가 일부 있었습니다.

VFX 그래프로 슈팅 시스템 최적화

슈팅 시스템에서는 다양한 효과가 사용되며, 이러한 효과는 게임 속도, 플레이어 수, 플레이하는 영역의 지형(topology), 현재 게임 상태에 따라 성능이 달라집니다. 즉, 많은 오브젝트가 주변에 생성되며(예: 임팩트(impact)) 씬 그래프가 다양한 드로우 콜(draw call)로 채워집니다.

FPS는 임팩트 64개의 풀을 사용하여 구현되었으며, 재사용 시스템(임팩트당 파티클 시스템 1개 + 오디오 소스 1개)을 기반으로 엔티티 컴포넌트 시스템(Entity-Component System)을 통해 관리됩니다.

이 시스템에서 나타난 주요 문제점은 임팩트의 모든 인스턴스가 드로우 콜을 시스템별로 발생시킨다는 것이었습니다. 효과별로 적은 수의 드로우 콜을 사용해야 한다는 제약이 있는데, 여기서는 최악의 경우 각 임팩트마다 N x 64개의 드로우 콜이 발생할 수 있습니다(N = 각 임팩트를 구성하는 파티클 시스템 수).

공유 시스템 구현

빠르게 개선된 기능 중 하나는 단일 무기(single weapon) 유형에 설정된 모든 종류의 임팩트에 하나의 공통 시뮬레이션을 사용할 수 있게 된 것입니다. 이 방식으로 모든 렌더링이 동일한 시뮬레이션에서 수행됩니다. 유니티는 각 임팩트를 개별적으로 정렬하지 않고 모든 임팩트 시스템을 함께 정렬할 때 발생할 수 있는 문제점을 감수하고, 대신 다음과 같은 이점을 최우선으로 고려하였습니다.

  • 시스템별로 훨씬 더 많은 파티클을 렌더링할 수 있음 – GPU 시뮬레이션에 더 효율적
  • 더 많은 파티클 시스템(레이어)을 사용하여 더 풍부한 효과 연출
  • 카메라까지의 거리(distance-to-camera)를 계속 계산할 수 있기 때문에 일종의 LOD 수행 가능

이 작업을 수행하기 위해 VFX SendEvent() API와 VFXEventAttribute 페이로드를 사용하여 임팩트 소스 및 임팩트 노멀을 지정했습니다.

 

임팩트 정의는 에셋 템플릿만 참조하며 씬 레벨 관리자가 마스터 시뮬레이션 오브젝트 처리와 이벤트 전송을 담당합니다. 아래의 VFXSystems 를 살펴보겠습니다.

VFXSystem은 FPS 샘플용으로 개발된 최상위 클래스로 풀링된 모든 효과를 처리합니다. 동작은 다음과 같습니다.

  • 플레이어가 VFXSystem에서 처리해야 하는 풀링된 효과를 트리거합니다.
  • VFXSystem은 이 효과의 속성(임팩트의 경우 포지션/노멀)을 가져옵니다.
  • VFXSystem은 이 효과의 템플릿도 가져옵니다.
  • 템플릿이 아직 생성되지 않았으면 생성합니다.
  • Unity는 두 가지 방법 중 하나를 사용하여 인스턴스에서 사용하기 위해 임팩트 포지션 및 노멀에 해당한는 속성(attribute)에 해당하는 페이로드함께 이벤트를 이 시스템에 전송합니다.
  • 레벨 변경 시 풀링된 효과를 리셋합니다. 이 커스텀 풀링 시스템은 성능 면에서 큰 개선이 이루어졌지만 단점도 있습니다.
  • 이벤트 속성으로 설계된 효과는 속성 때문에 C# API를 사용하여 트리거해야 하는데 이 방식은 미리볼 때와 효과 제작 시 좋은 방법은 아닙니다(VFX 이벤트 테스터에서 해결 방법 참조).
  • 효과를 커스터마이징하려면 큰 바운딩 박스(bounding box)를 사용해야 합니다. FPS 샘플에서는 전체 레벨을 포함하도록 경계 상자를 정적으로 설정했습니다. 여기서 중요한 점은 이 바운딩 박스를 C#으로 관리하여 실제처럼 생동감있는 가상의 임팩트로 커지거나 작아지도록 할 수도 있었다는 것입니다.
  • 효과 LOD는 생성 시간에 계산되므로 멀리 있는 임팩트는 항상 단순화됩니다(성능을 위해 의도적으로 수행).

VFX 이벤트 테스터

 

VFX 이벤트 테스터(VFX Event Tester)는 풀링된 효과에 대한 작업을 진행하던 매우 초기에 제공된 기능입니다. 이와 같은 효과는 이벤트 속성(임팩트 포지션 및 노멀, 총탄 명중 스캔 소스 및 타겟 포지션)을 사용하여 시작해야 하므로 이러한 속성을 저장하는 데 C#을 일부 사용해야 합니다.

처음 제공된 솔루션에서는 효과를 미리 보기 위해 파라미터화된 효과를 전송한 VFX 활성화 트랙(Activation Track)을 가진 더미 타임라인을 사용하는 것이었습니다. 이 경우 프리팹을 편집을 위해 씬에 포함했다가, 편집 후 제거해야 해서 비효율적이었습니다.

이를 대체하기 위해 유니티는 VFX 이벤트 테스터라는 씬 뷰(SceneView) 유틸리티 창을 개발했습니다. 이 창에서는 속성 페이로드가 있는 이벤트를 현재 선택된 에셋에 전송할 수 있습니다.

이 툴은 필요할 때 Edit > Visual Effects > Event Tester 메뉴에서 켜고 끌 수 있습니다. 소스 코드는 다음 위치에서 액세스할 수 있습니다.

Assets/VFX/VisualEffectGraph-Extras/Editor/Utility/VFXEventTester/VFXEventTesterWindow.cs

커스텀 파티클 LOD 시스템

모든 임팩트에 대해 항상 모든 효과 컴포넌트를 생성할 필요는 없으며 특히 매우 작은 파티클인 경우 더 그렇습니다. 유니티는 뎁스 의존적인(depth-dependent) 렌더링을 해결하기 위해 가장 기본적이면서도 유용한 파티클 필터링 시스템을 구현했습니다. 즉 거리를 기준으로 파티클 생성을 취소(Cancel By Distance)할 수 있었습니다. 이 시스템은 몇 가지 조건이 충족될 경우 파티클 생성을 무효화하는 하나의 방법이 됩니다.

이와 같은 간단한 LOD 시스템을 사용하여 임팩트에 거의 보이지 않는 파티클이 불필요하게 생성되지 않도록 할 수 있었습니다. 이 때 바위가 드릴에 부서지는 효과와 같은 멀리 떨어진 곳에서 발생하는 효과도 생성되지 않도록 해야 했습니다.

 

이 커스텀 생성 차단의 소스 코드는 다음 위치에서 찾을 수 있습니다. Assets/VFX/Script/CustomSpawners/CancelByDistance.cs

VFX 볼륨 믹서, 플레이어 주변 효과를 블렌딩

효과를 짧은 시간 안에 배치하는 경우 문제가 발생할 수 있으므로 플레이어의 카메라 주변에는 단일 효과를 사용하고, SRP 볼륨(SRP Volume) 시스템으로 포지션에 따라 플레이어 주변의 효과를 블렌딩하기로 했습니다.

 

볼륨 믹서(Volume Mixer)는 볼륨(Volume)이라는 SRP 코어 기능을 활용합니다. 이러한 클래스를 통해 볼륨 시스템에 저장된 파라미터(예: 렌더링 파라미터, 포스트 프로세스)를 사용하여 해당 레벨 내의 카메라 포지션에 따른 설정을 오버라이드할 수 있습니다.

이 시스템의 소스 코드는 다음 위치에서 액세스할 수 있습니다. Assets/VFX/Script/VFXVolumeMixer

이 시스템은 플레이어의 카메라의 위치에 상응하는 환경 효과를 배치하기 위해 사용되었으며, 실외/보일러실의 열 효과와 실내/동굴의 먼지를 생성합니다.

이 시스템을 사용하려면 프로젝트 설정에서 값을 설정해야 하며, 플로트 8개, 벡터 8개, 컬러 값 8개까지 조절할 수 있습니다. 설정에서 각 값을 몇 개씩 사용할 것인지를 선택하고, 변수에 이름을 지정할 수 있습니다.

그런 다음, 씬 볼륨에 VFX 볼륨 믹서(VFX Volume Mixer) 볼륨 컴포넌트를 추가하여 현재 레벨에서 오버라이드를 매우 간편하게 수행할 수 있습니다.

마지막으로, 이와 같은 볼륨에서 값을 샘플링하려는 경우에는 VFX 볼륨 믹서의 파라미터 바인더(Parameter binder)를 사용하면 됩니다.

Level_01 구현된 기타 주목할 만한 효과

FPS 샘플에는 Level_01 씬에서 사용했지만 일반 시스템에는 없는 일부 파티클 시스템도 구현되어 있습니다. 이번 샘플을 통해 해결한 사례는 다음과 같습니다.

캡처 포인트 써클

캡처 포인트 써클(Capture Point Circle)은 파티클이 16개의 컨트롤 포인트를 가지는 스킨드 튜브(skinned tube)로 만든 변형 가능한 경로를 따라다녀야 하므로 매우 재미있는 효과를 연출합니다. 비주얼 이펙트 그래프가 현재 스킨드 메시에서 파티클 생성(spawn)을 처리할 수 없기 때문에 Unity는 여전히 이 뼈대 체인(bone chain)에 대한 정보를 가지고 있습니다. 또한, 이 효과의 매끄러운 3D 보간을 위해 샘플 베지어 오퍼레이터(Sample Bezier operator)가 매우 유용하게 사용되었습니다.

 

여러 포지션으로 구성된 경로 상에서 파티클을 생성하기 위해 가장 확실한 방법은 포지션 속성 맵에 포지션 목록을 베이크한 다음 이 텍스처의 픽셀을 샘플링하여 파티클을 생성해야 하는 위치를 결정하는 것입니다.

이와 같이 특수한 경우를 위해 멀티플 포지션 바인더(Multiple Position binder)라는 새 파라미터 바인더를 작성했습니다. 이 바인더는 게임 오브젝트 목록을 가져와서 하나의 텍스처에 모든 게임 오브젝트의 월드 공간 포지션을 기록한 다음 포인트 수와 텍스처를 특정 비주얼 이펙트 그래프에 노출되는 파라미터로 설정합니다.

 

이 포지션 맵의 샘플링은 매우 간단합니다. 2 픽셀로 구성된 그룹 하나를 베지어 포인트 4개로 간주하고(2개의 중간 베지어 탄젠트를 계산하여) 모든 베지어 블렌딩을 통해 파티클이 모든 포지션을 통과하도록 보간합니다.

다음 위치의 프리팹에서 이 예제를 확인할 수 있습니다. Assets/Prefabs/Gameplay/Capturepoint_A. 해당 효과는 Small_emitter 게임 오브젝트에 구현되어 있습니다.

멀티플 포지션 바인더의 소스 코드는 다음 위치에 있는 프로젝트에서 사용할 수 있습니다. Assets/VFX/Script/ParameterBinders/VFXMultiplePositionParameterBinder.cs

암석 그라인더

암석 그라인더(Rock grinder)는 협곡 끝에 사용되는 간단한 데코레이션 효과입니다. 그라인딩 드릴(Grinding Drill)의 힘을 강조할 때 사용됩니다. 아래 동영상에 보이듯이 이 드릴은 고정되어 있으며 캡처 포인트가 되는 테라포머의 알(외계 바퀴벌레 알, Terraformer’s egg)뿐 아니라 왼쪽에 있는 암석층을 분쇄하고 있습니다.

먼지 배관 증기

모든 레벨에는 간단한 증기, 먼지, 기류 효과를 사용하여 꾸밀 필요가 있는 만은 광원이 있습니다. 대부분의 광원은 정적 소스이지만 이 회전하는 통풍관처럼 애니메이션화된 것도 일부 있습니다.

 

이러한 애니메이션 처리를 위해 릿(lit) 파티클을 사용하여 증기의 분출과 볼류메트릭 광선(volumetric light shaft)을 동기화했습니다. 적합한 프레임 속도를 유지하기 위해서는 이러한 파티클을 카메라와 멀리 떨어진 위치에서 페이드 아웃해야 했습니다. 셰이더가 픽셀마다 작동하도록 되어 있고, 전체 화면을 렌더링하려면 리소스를 너무 많이 사용해야 했기 때문입니다.

 

 

레벨 전체에 다른 효과도 설정되어 있었지만 이번에는 성능을 절약하기 위해 언릿(unlit) 파티클로 설정했습니다. 커다란 수직 통풍관도 밝힐 수 있었지만 크기 때문에 성능 면에서 문제를 일으킬 소지가 다분했습니다. 이에 더해 광선이 그다지 또렷하지 않았기 때문에 간단한 언릿 효과로 마무리했습니다. 이와 같은 모든 인스턴스는 페이드 거리 및 컬러를 설정하여 씬에서 직접 구성되었습니다.

용광로 효과

용광로 효과(Furnace Effect)는 동그란 모양으로 거품을 생성하고 실험 단계의 GPU 이벤트를 사용하여 거품이 터지는 플립북과 거품이 터질 때마다 위쪽에 반짝이는 효과를 생성하는 매우 간단한 효과입니다.

이 효과는 일반적으로 위치가 지정되지 않은 상태에서 위쪽으로 반짝이는 효과, 증기 및 열 효과를 사용하여 데코레이션됩니다.

이 효과를 좀 더 사실적으로 발전시킬 수 있었지만 오버드로우를 완화하고 프레임 속도를 제어 범위 내에서 유지할 수 있도록 증기와 열에 카메라 페이드 차단(Camera Fade block)을 사용했습니다.

 

결론

FPS 샘플에서 비주얼 이펙트 그래프로 전환하는 과정은 생각했던 것보다 원활하게 진행되었습니다. 패키지가 아직 프리뷰 버전으로 제공되어 프로젝트의 요구 수준에 맞게 환경을 커스터마이즈할 수 있는 유연성을 갖추고 있었기 때문입니다. FPS 샘플 프로젝트 구조는 매우 깔끔하고, 차선책이나 커스텀 구현이 거의 필요하지 않아 비주얼 이펙트 그래프 구현을 테스트하기가 매우 좋았습니다. 물론, 더 까다로운 프로젝트에서는 이와 전혀 다르게 더 힘든 과정이 되었을 수도 있었을 것입니다. 이러한 과정을 통해 2019년 비주얼 이펙트 그래프 업데이트에서는 어떤 제작 사례를 다룰지 정확히 짚어볼 수 있었습니다.

일부 기능은 통합을 위해 이번 샘플 사례에서 특별히 개발되었습니다. 유니티는 이러한 요소를 향후 좀 더 일반적인 정식 툴 개발에 기여할 수 있는 레퍼런스로 사용할 것입니다.

8 코멘트

코멘트 구독

코멘트를 달 수 없습니다.

  1. Great Post.

  2. Keep building on that game, please! Unity needs a real product to try all the new features. Also, try to use as few custom things as possible, as most of Unity’s “cinematics” released in the past use a ton of custom scripts/shaders that aren’t in the base engine. This project is looking good!

  3. Finally, a blog post worth reading. Though it’s miles better than other blogs, I thought the core of the FPS Sample is on the multiplayer where Unity lacks the most. I’ll appreciate if you focus more on the multiplayer rather than the eye-candies for FPS Sample. You can show the eye candies on other projects you have. Thanks.

  4. I definitly have to take a closer look at the visual effects graph. Thanks for this informativ post. Keep up the great work!

  5. This looks like an excellent “real-world” example (or close it) for the VFX Graph.

    Will you be providing a demo project that we can examine to better understand the details of your implementation?

  6. Florian Bässler

    4월 11, 2019 1:18 오전

    I am using Unity since years now, and i have to say, these whole FPS project is, for me, the best learning ressource (exspecilly for new features) unity ever provided. I am really happy to see, that you guys do a well progress there and keep us up to date. Thank you for sharing and helping me out finally understanding some advanced topics, i really could not figure out before!

  7. Marcin Szymanski

    4월 10, 2019 6:19 오후

    Fantastic post, can’t wait to dig into this on our next project!

  8. great post, more like these!