시퀀서 시간 리팩터링 테크니컬 노트

4.20 버전에서 시퀀서 툴에 시행한 시간 리팩터링 관련 기술적인 정보입니다.

Windows
MacOS
Linux

UE4 4.20 릴리즈에는 시퀀서 내 시간 표현 방식에 큰 변화가 생겼습니다. 프레임 정확도가 엄청나게 중요한 영화계 파이프라인과 컨텍스트를 더욱 잘 지원하기 위해서였습니다. 여기서는 일반적인 수준에서의 개념적 변화와, 업그레이드를 위해 C++ 코드 변경사항을 자세히 분석해 봅니다.

변경된 내용

애초에 시퀀서 는 시간을 부동 소수점 수 를 사용하여 단위로 표현해왔습니다. 그래서 완벽한 프레임 단위 정확도를 지원하기가 매우 힘들었으며, 키프레임 위치 오차, 렌더링 도중 오차, 카메라 컷 프레임 불안정, 평가 방식 모호성같은 문제가 생겼습니다. 언리얼 엔진 4.20 릴리즈 부터는 시간 표현에 정수 틱을 사용하도록 전환하여 위 문제가 전부는 아니더라도 많이 해결되었습니다.

이러한 틱 해석 방식은 시퀀스 단위로 정의되며, 시퀀스의 Tick Resolution (틱 해상도) 옵션으로 초당 틱 횟수를 정의합니다. 이 메커니즘을 사용하여, 사용자가 시퀀서 데이터의 입자성을 제어할 수 있습니다. 예를 들어, 프레임 정확도가 그리 중요하지 않은 실시간 어플리케이션이라면 초고해상도를 선택해도 되겠지만, 렌더링된 시네마틱의 마스터 시퀀스라면 그 프로젝트에 맞는 실제 프레임 속도를 선택해야 할 것입니다.

이 접근법은 안정성이나 퍼포먼스 저하 없이 각기 다른 컨텍스트에서 시퀀서에 뛰어난 유연성을 확보할 수 있습니다. 기본으로 4.20 이전 생성된 콘텐츠는 23.976 (NTSC) 를 제외한 일반적인 프레임 속도를 전부 아우르는 60,000 fps 틱 해상도로 업그레이드됩니다. 새 시퀀스는 기본 24,000 틱 해상도로 설정되며, 일반적인 정수 속도 전부는 물론 23.976 (NTSC) 도 커버합니다.

어떤 프로젝트든 사용할 수 있는 기본값 커스터마이징에 유용한 콘솔변수는 다음과 같습니다:

  • MovieScene.LegacyConversionFrameRate (기본: 60000fps)

    • 4.20 이전 저장된 UMovieScene 데이터에 대한 기본 프레임 해상도를 지정합니다.

    • 4.20 이상에서 (재)저장된 애셋에는 효과가 없습니다.

  • LevelSequence.DefaultTickResolution (기본: 24000fps)

    • 새로 생성되는 레벨 시퀀스의 기본 틱 해상도를 지정합니다.

  • LevelSequence.DefaultDisplayRate (기본: 30fps)

    • 새로 생성되는 레벨 시퀀스의 기본 디스플레이 프레임 속도를 지정합니다. 프레임 고정(locked) 설정된 시퀀스에 대한 프레임 고정 프레임 속도를 정의하기도 합니다.

참고로 시퀀서에 부동소수점 서브프레임을 사용하는 키프레임 데이터 평가 방식이 계속 지원됩니다. 틱 해상도가 매우 낮은 시퀀스에서도 실행시간에 부드러운 보간을 할 수 있다는 뜻입니다. 섹션 바운더리와 키프레임 자체만 틱 해상도의 제약을 받습니다.

어떤 시퀀스에 대한 모든 타이밍 정보는 이제 시퀀서 툴바의 Display Rate (디스플레이 속도) 드롭다운에 있으며, 툴팁에 현재 시퀀스의 틱 해상도가 설명됩니다:

이미지를 클릭하면 원본을 확인합니다.

이 메뉴에서 시퀀스의 디스플레이 프레임 속도, 시간 표시 모드, 평가 유형을 바꿀 수 있습니다. 현재 시퀀스의 틱 해상도와 호환되는 일반 디스플레이 속도는 맨 위에 표시됩니다.

틱 해상도와 호환되지 않는 프레임 속도를 사용한 디스플레이도 가능하지만, 추천하지는 않습니다.

생성한 이후, 시퀀스의 틱 해상도를 변경할 수는 있지만 현재 해상도의 배수가 아닌 틱 해상도로 시퀀스를 변환하면 고급 옵션 메뉴에서 찾을 수 있는 새 해상도로 섹션 바운더리와 키가 반올림될 수 있다는 점 주의하시기 바랍니다.

image alt text

C++ 업그레이드 노트

새 시간 포맷을 지원하기 위해, 시퀀서 내부 및 MovieScene 클래스 다수와 데이터 구조에 대한 대규모 재작업이 필요했습니다. 변경사항의 규모와 범위를 볼 때, 우아한 지원중단(deprate) 방법을 제공할 수 없는 API 가 몇몇 있었습니다.

여기서는 자세한 주요 변경사항 및 4.19 에서 4.20 으로 코드를 이주시키는 예제를 제공해 드립니다.

변경 및 추가 사항

  • TimeManagement 모듈: 일반적인 시간 관련 데이터 구조체와 조작 및 핸들링 유틸리티를 제공합니다:

코드

설명

FFrameNumber (32 비트)

형안전(typesafe) 32 비트 정수이며 주로 컨텍스트 없는 틱 또는 프레임 번호에 사용됩니다. int32 이외 다른 숫자 유형으로의 변환은 지원하지 않습니다.

FFrameTime (64 비트)

컨텍스트 없는 프레임 번호 및 부동소수점 서브 프레임으로 이루어진 시간 표현입니다. 주로 평가 도중 사용됩니다.

FFrameRate (64 비트)

정수 분자와 분모(프레임 / 초)로 저장되는 분수 프레임 속도입니다.

FQualifiedFrameTime (128 비트)

FFrameTime 과 FFrameRate 의 조합으로 초 값과 다른 프레임 속도 사이 편리한 상호 변환이 가능합니다.

FTimecode (20 바이트)

타임코드 표현으로 시간, 분, 초, 프레임에 정수, 드랍 프레임/논드랍 타임코드에 대한 부울 플래그를 포함합니다.

  • MovieScene 데이터: UMovieScene 에 이제 틱 해상도와 디스플레이 속도가 포함되어, 평가 유형 열거형으로 기존 ‘Force Fixed Frame Interval’ (고정 프레임 간격 강제) 평가 기능이 개선됩니다. UMovieScene API 의 주목할 만한 변경 사항은 다음과 같습니다:

코드

설명

UMovieScene::GetEvaluationType()

이 시퀀스 평가 방식을 정의하는 열거형을 구합니다:

코드

설명

WithSubFrames (기본)

서브 프레임으로 - 서브 프레임 보간을 사용하여 평가합니다.

FrameLocked

프레임 고정 - 시퀀스의 DisplayRate 에 고정시켜, 서브 프레임 없이 반올림된 프레임 번호만 평가하며, 평가 도중 t.maxfps 를 설정합니다.

UMovieScene::GetTickResolution()

이 무비 씬 내 모든 FFrameNumber 해석에 사용할 틱 해상도를 (달리 명시되지 않았으면) 구합니다.

UMovieScene::GetDisplayRate()

사용자향 UI, 블루프린트 노드, 시퀀스 플레이어가 이 시퀀스와 인터페이스 역할을 할 때 사용할 프레임 속도를 구합니다. EvaluationType 이 FrameLocked 로 설정된 경우 t.maxfps 와 고정 프레임을 정의하기도 합니다.

시간 관련된 무비 씬 데이터는 전부 소유한 UMovieScene 의 틱 해상도에 따라 FFrameNumber 를 사용하여 변환되었습니다. 포함된 내용은 다음과 같습니다:

  • UMovieSceneSection 범위. 섹션 범위는 이제 TRange 로 명시적 노출됩니다. 이 범위는 이제 무한 상하한으로 암시되기도 하므로, IsInfinite 플래그를 별도로 둘 필요가 없어집니다. 무한 범위를 지원하는 섹션은 이제 bSupportsInfiniteRange 를 true 설정하면 됩니다.

  • UMovieScene 재생 및 선택 범위. 포괄적 및 배타적 상하한 둘 다 제대로 처리됩니다.

  • 사전/사후 롤 양.

  • UMovieSceneSubSection 시작 오프셋 (내부 시퀀스의 틱 해상도 단위)

  • 커브 데이터: 기존 커브 클래스(, 예로 FRichCurve, FIntegralCurve, FNameCurve)는 모두 내부적으로 부동 소수점이 아닌, 소유 UMovieScene 의 틱 해상도 기준 FFrameNumber 시간 기반 새 채널로 대체됩니다. 부동 소수점 시간 표현과의 하위 호환성은 시간 유형의 불일치로 인해 가능하지 않습니다. SerializeFromMismatchedTag 를 통한 레거시 버전의 자동 업그레이드가 지원되며, 위 설명의 레거시 틱 해상도 업그레이드 방식을 사용합니다.

    • FRichCurve 는 FMovieSceneFloatChannel 이 됩니다.

    • FIntegralCurve 는 FMovieSceneIntegerChannel 이 됩니다.

    • FStringCurve 는 FMovieSceneStringChannel 이 됩니다.

    • FNameCurve 는 내부적으로 더이상 사용되지 않습니다.

    • FMovieSceneByteChannel (열거형 포함) 및 FMovieSceneBoolChannel 이 추가되었습니다.

이전에 TCurveInterface 를 사용하던 커스텀 커브 데이터 유형은 TMovieSceneChannelData<> GetData() 메서드를 제공하기만 하면 새로운 FMovieSceneXYZChannel 모델로 이주시키기 쉬울 것입니다.

무비 씬 채널

커브(, 이제 채널) 데이터를 어쩔 수 없이 크게 변경해야 했기에, 그 틈을 타 여러가지 에디터 코드패스를 취합시켜 키프레임을 지원하는 섹션에 대한 중복을 줄였습니다. 새로운 유형 FMovieSceneChannelProxy 가 추가되어, 에디터와 런타임 코드에 키프레임 조작 및 상호작용을 위한 공통 언어를 제공할 수 있습니다.

이를 위해 IKeyframeSection<> 이 완전 제거되어 더이상 필요하지 않습니다. 키프레임을 지원하는 섹션은 이제 채널 프록시만 제대로 채워주면 일반 키프레임 상호작용을 제대로 지원할 수 있습니다. 이 변경으로 인해 공통 키 조작 인터페이스가 이제 섹션 수준이 아닌 채널 수준에 존재하기 때문에 앞으로 키 프레임을 사용하여 새 섹션 유형을 구성하는 것이 훨씬 간단해집니다.

이 새로운 시스템에는 컴포넌트가 여럿 있으며, 에디터 커스터마이제이션에 대한 접근법이 약간씩 다릅니다:

FMovieSceneChannelProxy

UMovieSceneSection 에 저장되며, 파생형은 아래 예제와 같이 이 구조체에 모든 채널을 채워야 합니다. 채널은 기반 FMovieSceneChannel* 에 의해 파생 형식에 따라 버킷으로 저장됩니다. 이를 염두에 두고, 채널 재할당 이후 즉시 채널 프록시를 재생성해야 합니다. 그래야 이전 프록시에 저장된 채널에 대한 포인터와 핸들이 무효화됩니다.

채널과의 모든 상호 작용은 상황에 따라 FMovieSceneChannel 인터페이스로 직접 또는 ISequencerChannelInterface 를 통해 이루어집니다. 후자는 (ISequencerModule::RegisterChannelEditor) 시퀀서 모듈을 통해 유형별 등록됩니다.

이렇게 하지 않으면 해당 채널을 편집할 때 런타임에 어서션 오류가 발생합니다. 템플릿 기반 헬퍼는 TSequencerChannelInterface 를 통해 제공되며, 인수 종속 조회(ADL)를 통해 해결된 특정 채널 유형에 대한 단일 개념 오버로드를 허용합니다.

이렇게 하면 기본값이 대부분의 채널에 적합한 경우 전체 인터페이스를 다시 구현하지 않고도 특정 동작을 사용자 정의할 수 있습니다. 런타임 및 에디터에서 채널 레이아웃을 수동 정의하거나 ISequencerSection 인터페이스를 수동 정의하지 않고도 코어 시퀀서 코드가 채널 데이터에 대한 UI 를 자동으로 채울 수 있음을 의미합니다. 커스텀 섹션 유형을 생성하는 과정을 어느 정도 간소화시켜주며, 특히 이미 지원되는 고유(intrinsic) 채널 데이터에서 섹션을 합성할 때 그렇습니다.

ISequencerChannelInterface 기본 구현 함수는 시퀀서 네임스페이스에 정의되지만, 오버로드는 채널의 네임스페이스 또는 전역 네임스페이스에 추가해야 합니다.

커스텀 채널은 시간과 값을 병렬 배열에 저장하는 패턴을 따르고, 키 상호작용을 위한 TMovieSceneChannelData GetData() 메서드를 제공할 것을 추천합니다. FMovieSceneChannel 인터페이스 대부분은 TMovieSceneChannelData 에서 호출할 수 있는 함수에 직접 매핑됩니다.

이 프록시 방식을 사용하면 UI 를 구성하고 채널의 키와 상호작용하는 데 필요한 모든 데이터를 시퀀서 UI 코드에서 바로 사용할 수 있습니다.

FMovieSceneChannel

모든 공통 채널 데이터가 상호 작용할 수 있는 인터페이스를 제공합니다. 채널 프록시에 추가된 모든 채널은 이 유형을 구현해야 합니다.

ISequencerChannelInterface

지정된 채널에 대해 시퀀서가 요구하는 UI 상호작용 및 조작과 관련된 모든 오버로드에 대한 인터페이스입니다. (일반적으로 에디터 모듈의 StartupModule 메서드에 있는) 각 채널 유형에 대한 ISequencerModule 클래스를 통해 등록해야합니다.

TMovieSceneChannelTraits

확장 에디터 데이터와 같은 채널 유형에 대한 컴파일 타임 특성, 채널의 기본값 지원 여부를 지정합니다. 많은 시퀀서 UI 유틸리티는 MovieSceneChannelTraits.h 에 지정된 함수 오버로드를 사용하여 각 실제 채널 유형과 상호작용합니다. 기본 템플릿 기반 오버로드가 채널 유형과 호환되지 않는 경우 특정 채널에 필요한 기능을 오버로드해야 합니다.

기타 유틸리티

몇 가지 헬퍼 유틸리티가 추가되어 무비 씬 범위 작업이 쉬워졌습니다. 이제 이산 시간 기반을 사용하므로, 합리적인 섹션 바운더리 결정이 쉬워집니다. 내부 범위는 TRange 로 표현되며, 포괄적, 배타적, 열린 바운드를 지원합니다. 이 범위를 이산 시간 기반으로 처리하기 쉽게하기 위해 MovieScene :: DiscreteInclusiveLower, DiscreteExclusiveUpper 및 DiscreteSize 를 사용하여 다양한 바운더리 조건을 일관되게 처리할 수 ​​있습니다.

이주 가이드

이러한 변경 내용으로 인해, C ++에서 자체 트랙, 섹션 또는 커브를 작성한 경우 이주가 필요한 C ++ 변경 사항이 있습니다. 준비해 둔 이주 예제 프로젝트의 트랙, 섹션, 채널 유형을 확인하면 업그레이드에 도움이 될 수 있습니다.

태그
Select Skin
Light
Dark

새로운 언리얼 엔진 4 문서 사이트에 오신 것을 환영합니다!

문서 사이트에 대한 의견을 모을 수 있는 피드백 시스템을 포함해서 여러가지 새로운 기능을 준비하고 있습니다. 아래 Documentation Feedback 포럼(영문) 또는 언리얼 엔진 네이버 공식 카페(한글) 중 편하신 곳에 의견이나 문제점을 알려 주세요.

새 시스템이 준비되면 알려 드리겠습니다.

네이버 카페
공식 포럼