발자국, 물 튀김과 같은 이펙트
애니메이션 노티파이와 충돌 이벤트에서 지면 재질·위치·속도를 전달해 발자국 먼지와 물 튀김 효과를 스폰합니다.
기본적인 이펙트 제작 방법에서 만든 불꽃과 연기, 폭발은 레벨에 놓아 두면 혼자 재생되는 효과였습니다. 발자국(footstep) 먼지와 물 튀김(water splash)은 다릅니다. 캐릭터의 발이 땅에 닿는 순간이나 물체가 물에 떨어지는 순간에 맞춰 터져야 하고, 밟은 땅이 흙인지 눈인지, 얼마나 세게 떨어졌는지에 따라 모양도 달라져야 합니다. 그래서 나이아가라 시스템과 블루프린트를 함께 다뤄야 합니다. 이 글에서는 표면의 위치와 법선, 세기를 넘겨받는 발자국 먼지와 물 튀김 시스템을 만들고, 애니메이션 노티파이와 물 영역의 겹침으로 각각을 재생한 뒤, 두 효과가 속도를 다르게 읽는 계산을 따라가 봅니다.
발자국 먼지 시스템
발자국 효과는 캐릭터가 땅을 밟을 때 생기는 먼지나 흙먼지, 눈, 물 튀김처럼 여러 모양이 있습니다. 핵심은 발이 땅에 닿는 정확한 시점과 위치에 입자를 만드는 것입니다.
먼저 발자국에 쓸 나이아가라 시스템 NS_FootstepDust를 만듭니다. Fountain 이미터 템플릿을 담아 시작하며, 예전 버전의 창이라면 New system from selected emitters에서 Fountain을 고릅니다. 이 시스템은 한 번의 버스트로 입자를 만들므로 Emitter Update의 Spawn Rate는 지웁니다. 그리고 파라미터(Parameters) 패널의 User 섹션에서 +를 눌러 Float User.ImpactForce(발을 딛는 세기, 기본값 1.0)와 Vector User.GroundNormal(지면의 법선, 기본값 (0, 0, 1))을 만듭니다.
다음으로 초기값을 정합니다. Initialize Particle에서 Lifetime은 0.5초에서 1.0초 사이로 짧게, 스프라이트 크기는 작은 먼지에 맞게 5에서 15 사이로, 색은 땅의 재질에 맞게 흙먼지라면 갈색, 눈이라면 흰색으로 둡니다. Add Velocity는 Velocity Mode를 원뿔 방향(In Cone)으로 두고, 원뿔의 축을 월드 공간의 User.GroundNormal에 연결해 입자가 땅에서 위로 퍼지게 합니다. 속력에는 100 × Clamp(User.ImpactForce, 0, 2)cm/s처럼 단위를 정한 입력을 연결합니다. 시스템은 월드 공간으로 두고 만들 때의 회전은 0으로 써서, 법선 방향이 두 번 회전되지 않게 합니다.
그다음 움직임을 정합니다. Particle Update에서 Gravity Force는 약하게 주어 먼지가 천천히 가라앉게 하고, Drag는 강하게 주어 먼지가 빨리 느려지며 사라지게 합니다. Curl Noise Force는 약하게 주어 흐름에 작은 불규칙함을 더합니다. Collision을 추가한다면 충돌하면 입자를 없애는 응답을 고릅니다. 부딪혀 사라질 입자에는 반발이나 마찰을 다듬는 일이 중요하지 않습니다. 쓰는 CPU나 GPU 충돌 방식의 지원을 확인하고, Collision은 Solve Forces and Velocity 바로 앞에 둡니다.
이어서 Emitter Update에 Spawn Burst Instantaneous를 더하고, Spawn Count를 Clamp(Round(10 × User.ImpactForce), 0, 20)의 정수로 둡니다. 버스트 시간은 0, Emitter State는 Once로 두고, Particle State가 수명이 다한 입자를 없애게 합니다. 렌더링은 Sprite Renderer에 먼지나 연기 텍스처를 쓰는 Translucent 머티리얼을 지정하고, 머티리얼의 Opacity에 DepthFade를 적용해 표면과 만나는 자리를 부드럽게 한 뒤 시스템을 저장합니다.
애니메이션 노티파이에서 표면 조회하기
발이 땅에 닿는 프레임에 맞춰 입자를 만들 때는 애니메이션 노티파이(Animation Notify)를 쓰는 것이 일반적입니다. 노티파이를 애니메이션 타임라인에 놓고 이벤트로 받는 기본 방법은 언리얼 블루프린트 교재의 애님 몽타주와 노티파이의 기초에서 다룹니다. 먼저 캐릭터의 걷기나 달리기 애니메이션 시퀀스, 또는 애니메이션 몽타주를 엽니다.
언제나 같은 효과를 내는 단순한 경우라면, Add Notify > Play Niagara Particle Effect에서 나이아가라 시스템과 발 소켓을 지정하면 됩니다. 캐스케이드용인 Play Particle Effect와는 다른 노티파이입니다. 밟은 표면에 따라 효과를 나눠야 한다면, AnimNotify를 부모로 하는 블루프린트, 예를 들어 BP_AnimNotify_Footstep을 만들어 애니메이션 트랙에 놓습니다.
이 노티파이의 Received Notify에서는 다음 순서로 처리합니다. 먼저 넘겨받은 메시 컴포넌트에서 발 소켓의 위치를 구하고, 발 위에서 아래로 Line Trace By Channel을 하되 자기 캐릭터는 제외합니다. 트레이스의 입력과 Hit 결과를 읽는 법은 언리얼 블루프린트 교재의 환경 쿼리와 트레이싱 기본 활용에서 다룹니다. 막히는 Hit가 있을 때만 Impact Point와 Impact Normal, 그리고 Physical Material의 Surface Type을 읽는데, 땅의 머티리얼과 충돌 설정도 이 정보를 돌려주도록 구성되어 있어야 합니다. 다음으로 흙이나 눈, 물에 맞는 나이아가라 시스템을 고릅니다. 땅에 찍히는 발자국 데칼(Decal)의 수명은 순간적인 먼지와 따로 정합니다.
그다음 세기를 계산합니다. 메시 컴포넌트의 Owner에서 속도를 읽어 수평 속력을 구하고, ImpactForce = Clamp(Speed / 300, 0, 2)로 계산합니다. 이 값은 물리적인 힘이 아니라 이 예제가 정한 세기의 배율입니다. 이어서 Spawn System at Location의 Location에는 Impact Point에서 법선 방향으로 살짝 띄운 위치를, Rotation에는 0을 넣고 Auto Activate는 false로 둡니다. 돌려받은 컴포넌트가 유효한지 확인한 뒤 Set Niagara Variable (Float)로 User.ImpactForce를, Vector setter로 User.GroundNormal을 넘기고, 마지막에 Activate합니다. Spawn System at Location에는 사용자 파라미터를 넘기는 입력 핀이 없으므로, 값은 이렇게 돌려받은 컴포넌트에 넣습니다.
마지막으로 블루프린트와 애니메이션을 저장하고 게임을 플레이해, 캐릭터가 걸을 때마다 발밑에서 먼지가 이는지 확인합니다.
물 튀김 시스템
물 튀김은 물체가 얼마나 빠르게 떨어졌는지, 물이 얼마나 깊은지에 따라 다르게 나타납니다. 이 글의 예제는 물 표면에 들어오는 사건으로 스프라이트 물방울을 만드는 것이며, 나이아가라 Collision의 범용 유체 응답이나 실제 유체 시뮬레이션을 전제로 하지 않습니다.
먼저 Fountain 이미터 템플릿으로 NS_WaterSplash를 만들고, Emitter Update의 Spawn Rate를 지웁니다. 사용자 파라미터로는 Float User.SplashIntensity(물 튀김의 세기)와 Vector User.SurfaceNormal(물 표면의 법선)을 노출합니다.
다음으로 초기값을 정합니다. Initialize Particle에서 Lifetime은 0.5초에서 1.5초 사이로 짧게, 스프라이트 크기는 물방울에 맞게 5에서 20 사이로, 색은 하늘색이나 파란색 같은 물의 색으로 둡니다. 초기 속도는 Particle Spawn의 Add Velocity에서 원뿔 방향으로 정하는데, 월드 공간의 User.SurfaceNormal을 축으로 하고 속력은 200 × Clamp(User.SplashIntensity, 0, 2)cm/s로 둡니다.
그다음 움직임을 정합니다. Particle Update에서 Gravity Force를 강하게 주어 물방울이 빨리 떨어지게 하고, Drag는 약하게 주어 너무 빨리 멈추지 않게 합니다. Collision을 더한다면 CPU는 트레이스를, GPU는 지원되는 Scene Depth나 Distance Fields 방식 가운데 하나를 고르며, 두 시뮬레이션 대상의 옵션을 같은 메뉴로 다루지 않습니다. 부딪히면 없애는 응답을 쓴다면 반발이나 마찰보다 충돌을 감지하는 것이 중요하므로, 물 표면이 그 충돌 입력에 실제로 있는지 확인합니다. Solve Forces and Velocity는 Collision 바로 뒤에 두고, Particle State가 수명 종료를 처리하게 합니다.
이어서 Spawn Burst Instantaneous를 더하고, Spawn Count = Clamp(Round(20 × User.SplashIntensity), 0, 40)으로 정수 개수를 제한합니다. 버스트 시간 0과 Emitter State의 Once로 한 번만 터지게 합니다. 렌더링은 Sprite Renderer에 물방울 텍스처를 쓰는 Translucent나 Additive, Unlit 머티리얼을 지정하고 시스템을 저장합니다.
블루프린트에서 물 튀김 재생하기
물체가 물에 잠기는 경우라면, 막는 벽처럼 동작하는 Blocking Volume보다 물 영역의 겹침(overlap)과 별도의 표면 조회를 쓸 수 있습니다. 아래 예는 수면의 높이 Z를 알고 있는 수평한 물을 가정합니다.
먼저 물 영역 컴포넌트의 Overlap 응답과 Generate Overlap Events를 맞추고, 물 영역의 참조나 인터페이스로 대상을 알아봅니다. 다음으로 BP_ThrowableRock의 Begin Overlap에서 물 영역에 들어왔는지 확인합니다. 여러 컴포넌트가 겹쳐도 같은 진입에는 한 번만 터지도록 상태를 저장하고, 영역을 완전히 나간 뒤에 다시 초기화합니다.
그다음 물체 위치의 X, Y와 수면의 Z로 표면의 위치를 정하고, Surface Normal은 (0, 0, 1)로 둡니다. 실제 물 시스템을 쓴다면 그 시스템이 돌려주는 표면 높이와 법선으로 바꿉니다. 일반적인 Overlap의 Sweep Result가 언제나 유효한 Impact Point를 준다고 가정하지 않습니다. 이어서 들어올 때 속도의 아래쪽 성분으로 SplashIntensity = Clamp(Max(0, -Velocity.Z) / 500, 0, 2)를 계산하고, Spawn System at Location의 Auto Activate를 false로 둔 뒤 돌려받은 컴포넌트에 User.SplashIntensity와 User.SurfaceNormal을 넣고 Activate합니다.
마지막으로 저장과 컴파일을 하고 천천히 들어갈 때와 빠르게 떨어질 때, 다시 들어갈 때를 비교합니다. 실제로 실행해 보기 전에는 위 값에 따른 개수와 높이를 예상으로만 다룹니다.
막히는 표면의 Hit를 쓰는 구성이라면 Other Comp와 Impact Point, Normal을 확인합니다. Component Hit의 Hit Component는 이벤트를 가진 쪽의 컴포넌트입니다. Hit에는 일반적인 Velocity 출력 핀이 없고, 쓸고 지나가는(sweep) 충돌의 Normal Impulse는 0일 수 있으므로, 필요하면 충돌 직전의 속도를 저장해 둡니다.
두 효과는 속도를 다르게 읽는다
발자국과 물 튀김은 같은 속도라도 서로 다른 성분을 읽습니다. 발자국의 입력 속도가 (180, 240, 0)cm/s라면 수평 속력은 sqrt(180² + 240²) = 300cm/s입니다. 그러면 ImpactForce는 300 ÷ 300 = 1, 먼지의 Count는 10, 원뿔의 속력은 100cm/s입니다. ImpactForce는 뉴턴 단위의 충돌 힘이 아니라 이 예제가 정한 배율입니다.
반면 물체가 Z 방향으로 -750cm/s로 수면에 들어오면, SplashIntensity는 750 ÷ 500 = 1.5이고 물방울의 Count는 30, 원뿔의 속력은 300cm/s입니다. 물 튀김의 예제는 수평 속력 대신 아래 방향의 성분을 읽기 때문입니다.
| 효과 | 읽는 성분 | 기준값 | 세기 | Count | 원뿔 속력 |
|---|---|---|---|---|---|
발자국 (180, 240, 0) | 수평 속력 300cm/s | 300 | 1 | 10 | 100cm/s |
물 튀김 (0, 0, -750) | 아래 방향 750cm/s | 500 | 1.5 | 30 | 300cm/s |
자주 터지는 효과의 비용
발자국과 물 튀김은 자주 터지는 효과이므로 비용을 더 신경 써야 합니다. 입자의 수명을 되도록 짧게 해 동시에 살아 있는 입자 수를 줄이고, 화면 품질을 해치지 않는 선에서 버스트의 개수를 줄입니다. 머티리얼은 Unlit에 Translucent나 Additive를 쓰는 단순한 텍스처 머티리얼로 둡니다.
Collision은 복잡한 설정을 피하고, 부딪히면 없애는 응답을 쓰거나 충돌이 필요 없는 입자에서는 모듈을 뺍니다. 발자국처럼 아주 자주 생기는 효과는 Spawn 노드에 내장된 Pooling Method를 먼저 검토합니다. 저절로 회수되는 컴포넌트의 참조를 효과가 끝난 뒤에 다시 쓰지 않고, 한 번 재생되는 시스템이 실제로 완료되는지 확인합니다.
두 효과 모두 표면의 위치와 법선, 세기를 먼저 정하고, 값을 넣은 컴포넌트를 켜는 순서를 따릅니다. 다만 발자국은 땅에 닿는 노티파이로, 물 튀김은 영역에 들어오는 사건으로 터지므로, 공중에서 걷는 경우와 중복된 겹침, 기본 표면 타입도 함께 확인합니다.
정리
- 발자국과 물 튀김은 사건에 맞춰 한 번 터지는 효과로,
Spawn Rate를 지우고Spawn Burst Instantaneous와Once루프로 만듭니다. - 시스템은 세기와 법선을 사용자 파라미터로 받아, 원뿔 방향의 축과 속력, 버스트 개수에 연결합니다.
- 발자국은 애니메이션 노티파이에서 아래로 트레이스해 막히는 Hit가 있을 때만 위치와 법선, 표면 타입을 읽어 재생합니다.
- 물 튀김은 물 영역의 겹침에서 한 번만 재생하고, 수면의 위치와 법선은 알려진 높이나 물 시스템의 조회로 정합니다.
- 두 효과의 세기는 각각 수평 속력과 아래 방향 성분으로 정한 배율이며, 물리적인 힘이 아닙니다.
연습 문제
1. 같은 속도, 두 효과
이번 입력은 속도 (-360, 480, -250)cm/s입니다. 유효한 지면 Hit와 첫 수면 진입이 각각 확인되었다고 할 때, 두 효과의 세기와 Count, 원뿔 속력을 계산해 보세요. 지면 트레이스가 실패했을 때도 속력 계산만 맞으면 먼지를 만들어도 될까요?
해설 보기
수평 속력은 sqrt(360² + 480²) = 600cm/s이므로, 발자국은 세기 Clamp(600 ÷ 300, 0, 2) = 2, Count 20, 속력 200cm/s입니다. 물 튀김은 아래 방향 성분 250cm/s로 세기 250 ÷ 500 = 0.5, Count 10, 속력 100cm/s입니다.
트레이스가 실패하면 유효한 표면 정보가 없으므로 먼지를 만드는 경로로 가지 않습니다. 돌려받은 Spawn 값이 유효하지 않을 때도 값 넣기와 Activate를 하지 않습니다. 두 Count는 입력이 유효하고 그 버스트가 실행될 때 요청하는 값이지, 실제로 만들어진 입자를 잰 기록이 아닙니다. 수면 안에서 여러 컴포넌트가 더 겹치더라도 같은 진입을 새 버스트로 중복 처리하지 않습니다.
2. 한 번 떨어졌는데 여러 번 튀는 물
돌을 한 번 물에 던졌는데 물 튀김이 세 번 연달아 터집니다. 돌은 Static Mesh와 Sphere Collision 등 컴포넌트 세 개로 이루어져 있습니다. 왜 그럴까요?
해설 보기
돌의 컴포넌트 세 개가 각각 물 영역과 겹치면서 Begin Overlap이 세 번 왔고, 그때마다 물 튀김을 재생했을 가능성이 큽니다.
물에 들어왔다는 상태를 저장해 두고, 이미 들어온 상태라면 더 재생하지 않게 합니다. 그리고 모든 컴포넌트가 영역을 완전히 나간 뒤에 상태를 초기화하면, 한 번의 진입에 한 번만 터집니다.
3. 기울어진 땅에서 옆으로 퍼지는 먼지
경사진 땅에서 걸으면 발자국 먼지가 땅에서 수직으로 피어나지 않고 한쪽으로 크게 기울어 퍼집니다. 원뿔의 축은 User.GroundNormal에 연결되어 있습니다. 무엇을 확인해야 할까요?
해설 보기
시스템을 만들 때 Rotation에 법선 방향의 회전을 넣었는지 확인합니다. 원뿔의 축이 이미 월드 공간의 User.GroundNormal을 따르는데 시스템까지 법선으로 회전시키면, 방향이 두 번 회전되어 엉뚱하게 기웁니다.
이 예제처럼 시스템은 월드 공간으로 두고 만들 때의 회전은 0으로 두거나, 반대로 시스템을 법선 방향으로 회전시킨다면 원뿔의 축을 로컬 +Z로 둡니다. 두 방법 가운데 하나만 씁니다.
노티파이의 종류는 Epic의 나이아가라 퀵스타트에서, 시스템을 만드는 노드의 입력은 Spawn System at Location 노드 문서에서 확인할 수 있습니다.
다음 글 기본적인 마법 및 능력 시각화에서는 오라와 발사체, 충격으로 나뉘는 마법 효과의 설정을 살펴보고, 블루프린트로 움직이는 얼음 파편 마법을 만들어 봅니다.