이 기능은 얼리 액세스 단계입니다. 이 기능을 사용하여 섬을 퍼블리싱할 수는 있지만, 얼리 액세스 기간 동안 일어난 변경사항으로 인해 섬이 정상적으로 작동하지 않아 크리에이터의 적극적인 개입이 필요할 수도 있습니다.
NPC 생성 장치에는 시퀀서의 바인딩 수명 트랙이 필요합니다. 31.00 이전에 만든 기존 시퀀스에 이 트랙을 소급해서 추가할 수 있는 방법은 없습니다. 바인딩 수명 트랙을 추가한 후 시퀀스에서 NPC 생성 장치를 사용하는 모든 섬을 다시 퍼블리싱해야 합니다.
바인딩 수명 트랙을 추가하려면 다음 단계를 따르세요.
-
트랙 목록에서 NPC 생성 장치(NPC Spawner) 옆의 + 아이콘을 클릭합니다.
-
드롭다운 메뉴에서 바인딩 수명(Binding Lifetime) 을 선택합니다.
시퀀서 를 사용하여 NPC 생성 장치 를 비롯한 여러 장치에서 다양한 방식으로 재생할 수 있는 커스텀 캐릭터 애니메이션을 제작합니다. 이벤트 또는 시퀀서 중 하나를 시네마틱 시퀀스 장치와 함께 사용하여 AI 순찰 경로 의 선택 지점을 따라 패턴화된 비헤이비어가 포함된 애니메이션을 설정 및 재생합니다.
메타휴먼을 비롯한 언리얼 엔진(UE)의 커스텀 애니메이션을 이주 및 임포트할 수 있습니다. 포트나이트 캐릭터에는 자체적인 스켈레탈 구조가 있으므로, 이주 및 임포트를 위해서는 스켈레탈 메시를 NPC 캐릭터에 맞춰 리타기팅해야 할 수 있습니다.
메타휴먼 캐릭터는 메모리 집약적입니다. 사용하는 메타휴먼 에셋의 수를 제한하는 것이 가장 좋습니다.
시퀀서에서 NPC 애니메이팅하기
인터랙티브 캐릭터부터 정보성 컷신까지, NPC 생성 장치를 통해 프로젝트에 다채롭고 창의적인 게임플레이를 구현할 수 있습니다. 컨트롤 릭 으로 NPC 생성 장치용 커스텀 애니메이션을 제작하거나, 구매했거나 다른 소프트웨어에서 제작한 애니메이션을 임포트할 수 있습니다.
FK 컨트롤 릭 을 사용하여 리타기팅된 애니메이션 또는 이모트로 NPC를 애니메이팅할 수 있습니다.
UE 문서에서 FK 컨트롤 릭 애니메이션 워크플로에 대해 자세히 알아보세요.
NPC 캐릭터가 있는 애니메이션을 캡처하려면 다음 단계를 따릅니다.
-
콘텐츠 브라우저(Content Browser) 에서 우클릭하여 레벨 시퀀스(Level Sequence) 를 생성합니다.
-
레벨 시퀀스 섬네일의 이름을 변경합니다.
-
레벨 시퀀스 섬네일을 더블 클릭하여 시퀀서 에디터 를 엽니다.
-
+트랙(+Track) 을 클릭한 다음 액터를 시퀀서로(Actor to Sequence) > NPC 생성 장치(NPC Spawner) 를 선택합니다. 이렇게 하면 레벨 시퀀스 트랙에 NPC 생성 장치가 추가됩니다.
NPC 생성 장치를 아웃라이너(Outliner) 의 트랙 목록에 드래그하여 레벨 시퀀스에 추가할 수 있습니다.
-
트랙 목록에서 NPC 생성 장치 옆의 + 아이콘을 클릭하고 컨트롤 릭(Control Rig) > 컨트롤 릭 클래스(Control Rig Classes) > FK 컨트롤 릭(FK Control Rig) 을 선택합니다. 이렇게 하면 트랙에 NPC 스켈레톤이 추가되어 스켈레톤의 개별 본에 액세스하여 조작 및 녹화할 수 있습니다.
-
뷰포트, 애님 아웃라이너(Anim Outliner) 또는 시퀀서에서 이동하려는 본을 선택하고 애니메이션의 시작 위치로 본을 이동합니다.
-
이동한 본 옆의 + 아이콘을 클릭하여 첫 번째 키프레임을 설정합니다.
제작했거나 구매한 애니메이션을 FBX 애니메이션 시퀀스 파일로 보유한 경우, NPC 생성 장치 옆의 + 아이콘을 클릭하고 애니메이션(Animation) > 애니메이션 파일(Animation file) 을 선택하여 타임라인에서 NPC 생성 장치의 애니메이션 트랙에 해당 파일을 추가할 수 있습니다.
애니메이션이 완료될 때까지 시퀀서 타임라인에서 계속해서 본을 이동하고 새 키프레임을 설정합니다. 애니메이션이 완료되면, 시퀀서에서 애니메이션을 재생하여 원하는 대로 움직임이 이루어지는지 확인합니다.
애니메이션을 역방향으로 재생하는 간단한 방법으로 타임라인에서 애니메이션 파일을 우클릭하고 프로퍼티(Properties) > 역방향(Reverse) 을 선택하는 것이 있습니다.
결과가 만족스럽다면, 스켈레탈 메시에 애니메이션을 구울 차례입니다. NPC 생성 장치를 우클릭하고 애니메이션 시퀀스 베이크(Bake Animation Sequence) 를 선택합니다.
애니메이션 재생 시 스켈레탈 메시의 팔다리가 스켈레탈 메시 바디의 다른 파츠와 겹치지 않는지 확인합니다.
비헤이비어 어트리뷰트 녹화하기
비헤이비어 어트리뷰트도 NPC 생성 장치와 함께 사용할 수 있습니다. 비헤이비어 옵션은 NPC가 포트나이트 배틀로얄 NPC로부터 상속받는 기본 특성을 결정합니다. 이러한 특성은 NPC가 경비나 야생동물처럼 행동하는지 여부를 결정합니다.
NPC 생성 장치로 비헤이비어 어트리뷰트를 설정하는 방법에 대한 자세한 내용은 NPC 캐릭터 정의 문서를 참조하세요.
이러한 비헤이비어 어트리뷰트를 구성했다면 레벨 시퀀스에서 애니메이션의 키프레임을 지정하고 게임플레이 중에 시네마틱 시퀀스 장치에서 해당 애니메이션을 재생할 수 있습니다. 위의 단계와는 달리, 비헤이비어는 NPC 생성 장치의 옵션에서 설정되기 때문에 퍼포먼스를 컨트롤 릭에 구울 필요가 없습니다.
AI 순찰 경로 지점 장치에도 제작한 애니메이션 또는 상속받은 비헤이비어를 사용하여 시네 카메라 액터(Cine Camera Actor) 로 생성한 경로를 따라 NPC를 녹화할 수 있습니다.
생성 가능 및 대체 가능 NPC 바인딩
이제 NPC를 시퀀스에 가져오는 방법이 두 가지 더 생겼습니다. 생성 가능 NPC 바인딩과 대체 가능 NPC 바인딩입니다. 이러한 바인딩은 NPC 캐릭터 정의에서 생성됩니다.
생성 가능 NPC 바인딩
시네마틱 시퀀스를 사용하면 생성 가능 NPC 바인딩(spawnable NPC binding) 을 통해 NPC 캐릭터 정의(NPC Character definition) 에 따라 월드에 액터를 생성할 수 있습니다. 이 NPC는 스켈레탈 메시와 동일한 방식으로 시퀀서에서 애니메이션을 적용할 수 있습니다.
생성 가능 NPC 바인딩을 만들려면 NPC 캐릭터 정의를 시퀀서로 드래그하기만 하면 됩니다.
gif를 클릭하면 확대됩니다.
생성 가능 바인딩은 다른 스켈레탈 메시 액터와 마찬가지로 애니메이션을 적용할 수 있습니다. 예를 들면 다음과 같습니다.
-
+ 애니메이션(+ Animation) 을 클릭하고 NPC 캐릭터 정의를 위한 댄스 이모트를 선택합니다.
gif를 클릭하면 확대됩니다.
-
플레이헤드를 더 앞으로 옮기고, NPC를 새로운 위치로 드래그하고, 새 키프레임을 설정합니다. 이제 NPC가 A지점에서 B지점으로 이동합니다.
gif를 클릭하면 확대됩니다.
대체 가능 NPC 바인딩
대체 가능 NPC 바인딩(replaceable NPC binding) 은 월드에 생성된 NPC를 제어하고 시퀀스에 배치합니다. 그런 다음 시퀀서에서 만든 애니메이션을 실행할 수 있습니다. NPC가 시퀀서에 바인딩되는 동안 모든 행동, 인식 및 경로 따라가기가 일시정지됩니다. 이는 NPC 바인딩이 해제되면 재개됩니다.
NPC는 더 이상 바인딩되지 않을 때 원래 위치로 다시 배치됩니다.
대체 가능 NPC 바인딩을 만들려면 생성 가능 NPC 바인딩을 만들고 바인딩을 우클릭한 다음 선택한 바인딩을 다음으로 변환(Convert selecting binding to) > 대체 가능 NPC 캐릭터(Replaceable NPC Character) 를 선택합니다.
gif를 클릭하면 확대됩니다.
변환 후 트랙은 바인딩 수명 트랙으로 대체됩니다. 생성 가능 바인딩에 적용된 모든 변경사항은 유지됩니다.
게임플레이 중 NPC를 찾아 바인딩하려면 NPC 캐릭터 정의에 시퀀서 모디파이어 를 추가해야 합니다. 다른 모디파이어와 같은 방법으로 NPC 캐릭터 정의에 이를 추가할 수 있습니다. 이 모디파이어를 추가하지 않으면 유효성 검사에 실패합니다.
gif를 클릭하면 확대됩니다.
시퀀서 모디파이어에는 고유 식별자(Unique Identifier) 프로퍼티가 있습니다. 이 프로퍼티는 게임에서 생성된 NPC를 찾는 데 사용됩니다. 기본값은 NPC 캐릭터 정의의 이름입니다. 두 개의 서로 다른 NPC 캐릭터 정의에 동일한 고유 식별자가 있는 경우, 시퀀스가 게임에서 재생될 때 둘 다 바인딩될 수 있습니다.
게임에서 시퀀스 재생하기
시퀀스를 재생하려면 일반적으로 시네마틱 시퀀스 장치를 사용합니다.
생성 가능 바인딩은 재생하는 데 추가 구성이 필요하지 않습니다.
대체 가능 바인딩을 사용하려면 NPC 캐릭터 정의를 사용하는 NPC 생성 장치를 월드에 추가해야 합니다. 대체 가능 바인딩이 바인딩할 NPC를 찾지 못하는 경우, 클라이언트 로그에 다음 줄이 표시됩니다.
LogFortNPCMovieSceneBindings: Warning: Could not bind to a pawn using NPC Character Definition Guard. Please ensure there is at least one spawned.
시퀀스를 재생하는 것과 동시에 NPC를 생성하려는 경우 생성 가능 바인딩 사용을 고려하거나 생성 시(On Spawn) 이벤트 를 시네마틱 시퀀스 장치의 Play 함수에 연결하세요.
커스텀 블루프린트 NPC
대부분의 NPC 타입은 스켈레탈 메시로 바인딩되지만, 커스텀 블루프린트를 사용하는 NPC 캐릭터 정의는 예외입니다.
블루프린트에 바인딩되고, VFX와 같은 추가 컴포넌트가 노출되어 시퀀서에서 수정할 수 있습니다.
여기서는 NPC의 머리가 폭발하도록 시퀀서에서 나이아가라 파티클 시스템이 수정된 것을 볼 수 있습니다.
gif를 클릭하면 확대됩니다.
알려진 제한 사항
- 대체 가능 NPC 바인딩은 공개 상태(Visibility): 모두(Everyone) 로 설정된 시네마틱 시퀀스 장치에서만 사용할 수 있습니다. 다른 비저빌리티 세팅을 사용하면 유효성 검사에 실패합니다.
- 탈 수 있거나 길들일 수 있는 야생동물 NPC에 대체 가능 NPC 바인딩을 사용하려고 하면 유효성 검사에 실패합니다.
- NPC 캐릭터 정의를 사용하는 대체 가능 NPC 바인딩은 완료 상태 오버라이드 종료(Finish Completion State Override) 사용자 옵션에서 강제 상태 유지(Force Keep State) 옵션을 사용할 수 없습니다. 이 옵션을 사용하려고 시도하면 유효성 검사에 실패합니다.
- NPC가 시퀀서에 바인딩되면 제자리에 스냅됩니다. 또한, NPC가 바인딩되거나 바인딩 해제될 때 지연시간 문제로 인해 매우 짧은 시각적 버그가 발생할 수 있습니다. 따라서 대체 가능 NPC 바인딩을 사용할 때는 NPC를 화면 밖에서 생성하기, 화면 페이드, VFX 또는 비저빌리티 트랙과 같은 기법을 활용하는 것이 좋습니다.
Verse로 애니메이션 호출하기
에셋 리플렉션을 사용하여 Verse에 애니메이션을 노출하면 애니메이션 모듈을 통해 NPC에 커스텀 애니메이션을 재생할 수 있습니다.
애니메이션 컨트롤러 인터페이스
play_animation_controller 인터페이스를 통해 캐릭터에 애니메이션을 재생할 수 있으며, 해당 인터페이스는 GetPlayAnimationController() 함수로 얻을 수 있습니다. 이 인터페이스는 애니메이션을 재생하는 2개의 함수인 동기식 Play() 함수와 비동기식 PlayAndAwait() 함수를 노출합니다.
두 함수 모두 다음과 같은 파라미터를 수락합니다.
| 옵션 | 값 | 설명 |
|---|---|---|
| Animation | 애니메이션 선택 | 재생할 애니메이션입니다. Assets.digest.verse 파일에서 애니메이션을 지정해야 엽니다. |
| PlayRate | 1.0, 재생 속도 선택 | 애니메이션을 재생할 속도입니다. 값이 1.0이면 애니메이션의 디폴트 속도에 해당합니다. |
| BlendInTime | 0.0, BlendInTime 선택 | 이전 애니메이션을 현재 애니메이션에 블렌딩할 시간입니다. |
| BlendOutTime | 0.0, BlendOutTime 선택 | 현재 애니메이션을 다음 애니메이션에 블렌딩할 시간입니다. |
| StartPositionSeconds | 0.0, StartPositionSeconds 선택 | 애니메이션 재생을 시작할 위치(초)입니다. |
Play And Await 함수
PlayAndAwait() 함수는 애니메이션을 비동기식으로 재생하며, Completed , Interrupted , Error 라는 3개 값이 포함된 play_animation_result 열거형의 인스턴스를 반환합니다. 이 3개 값은 각각 완료된 애니메이션, 중단된 애니메이션, 발생한 오류에 해당합니다. 이 열거형을 쿼리하여 애니메이션 결과를 기반으로 다른 코드를 실행할 수 있습니다.
AnimationResult := PlayAnimController.PlayAndAwait(MyAnimation)
case(AnimationResult):
play_animation_result.Completed => Print("Animation Completed!")
play_animation_result.Interrupted => Print("Animation Interrupted.")
play_animation_result.Error => ("Error Occurred during animation.")
Play 함수
Play() 함수는 동기적으로 실행되며, playing_animation_instance 클래스의 인스턴스를 반환합니다. playing_animation_instance 클래스는 진행 중인 애니메이션을 쿼리 및 조작하도록 하며, 다음 값이 포함되어 있습니다.
| 값 | 설명 |
|---|---|
| GetState() | 이 함수는 play_animation_state 열거형에서 애니메이션 재생의 현재 상태를 반환합니다. |
| Stop() | 이 함수는 현재 애니메이션을 중지합니다. |
| CompletedEvent | 이 이벤트는 애니메이션 완료 시 트리거됩니다. |
| InterruptedEvent | 이 이벤트는 애니메이션 중단 시 트리거됩니다. |
| BlendedInEvent | 이 이벤트는 애니메이션의 블렌드 아웃이 종료되면 트리거됩니다. |
| BlendingOutEvent | 이 이벤트는 애니메이션의 블렌드 아웃이 시작되면 트리거됩니다. |
| Await() | 이 함수는 애니메이션이 완료되거나 중단되기를 기다립니다. 특히, 이 함수는 play_animation_result 열거형을 반환하며, PlayAndAwait() 호출과 기능상 동일합니다. |
애니메이션 내 특정 조건이 충족되면 Play() 함수를 사용하여 진행 중인 애니메이션을 조작하거나 코드를 실행할 수 있습니다.
# 애니메이션을 동기식으로 재생하고 해당 애니메이션 인스턴스를 얻습니다.
AnimationInstance := PlayAnimController.Play(MyAnimation, ?PlayRate := PlayRate, ?BlendInTime := BlendInTime, ?BlendOutTime := BlendInTime, ?StartPositionSeconds := StartPositionSeconds)
# 애니메이션이 완료되면 실행되는 함수를 등록합니다.
AnimationInstance.CompletedEvent.Subscribe(OnAnimationComplete)
Sleep(1.0)
AnimationState := AnimationInstance.GetState()
# 1초 후 애니메이션이 여전히 재생 중인 경우, 애니메이션을 중지합니다.
if(AnimationState = play_animation_state.BlendingOut):
AnimationInstance.Stop()
애니메이션 재생 예시
아래의 코드는 애니메이션 모듈을 사용하여 애니메이션을 재생하는 NPC 비헤이비어의 예시를 보여줍니다. 캐릭터에 재생하려는 모든 커스텀 애니메이션은 에셋 리플렉션을 통해 Verse에 먼저 노출되고 Assets.digest.verse 파일에 표시되어야 한다는 점에 유의하세요. 이 예시에서는 MyAnimation이라는 애니메이션이 Assets.digest.verse 내 커스텀 MyCharacter 캐릭터의 애니메이션 모듈에 위치해 있으며, 따라서 MyCharacter.Animations.MyCharacter를 통해 호출됩니다.
using { /Fortnite.com/AI }
using { /Fortnite.com/Animation/PlayAnimation }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
basic_play_anim_example := class(npc_behavior):
# 애니메이션을 재생할 속도입니다.
@editable
PlayRate : float = 1.0
# 이전 애니메이션을 현재 애니메이션에
# 블렌딩할 시간입니다.
@editable
BlendInTime : float = 0.25
# 현재 애니메이션을 다음 애니메이션에
# 블렌딩할 시간입니다.
@editable
BlendOutTime : float = 0.25
# 애니메이션 재생을 시작할
# 위치(초)입니다.
@editable
StartPositionSeconds : float = 0.0
# 애니메이션 재시작 전 기다릴 시간입니다.
@editable
SleepDuration : float = 2.0
OnBegin<override>()<suspends>:void=
if:
# NPC 캐릭터의 애니메이션 컨트롤러를 얻습니다.
Agent := GetAgent[]
FortCharacter := Agent.GetFortCharacter[]
PlayAnimController := FortCharacter.GetPlayAnimationController[]
then:
AnimationResult := PlayAnimController.PlayAndAwait(MyCharacter.Animations.MyAnimation, ?PlayRate := PlayRate, ?BlendInTime := BlendInTime, ?BlendOutTime := BlendInTime, ?StartPositionSeconds := StartPositionSeconds)
# 애니메이션 실행 결과를 출력합니다.
case(AnimationResult):
play_animation_result.Completed => Print("Animation Completed!")
play_animation_result.Interrupted => Print("Animation Interrupted.")
play_animation_result.Error => ("Error Occurred during animation.")
Sleep(SleepDuration)
# 애니메이션을 동기식으로 재생하고 해당 애니메이션 인스턴스를 얻습니다.
AnimationInstance := PlayAnimController.Play(MyCharacter.Animations.MyAnimation, ?PlayRate := PlayRate, ?BlendInTime := BlendInTime, ?BlendOutTime := BlendInTime, ?StartPositionSeconds := StartPositionSeconds)
Sleep(SleepDuration)
AnimationState := AnimationInstance.GetState()
# 애니메이션의 현재 상태를 출력합니다.
case(AnimationState):
play_animation_state.Playing => Print("Animation Playing!")
play_animation_state.BlendingIn => Print("Animation Blending In!")
play_animation_state.BlendingOut => Print("Animation Blending Out!")
play_animation_state.Completed => Print("Animation Completed!")
play_animation_state.Stopped => Print("Animation Stopped!")
play_animation_state.Interrupted => Print("Animation Interrupted!")
play_animation_state.Error => Print("Error Occurred During Animation")
else:
Print("Could not get animation controller")