액터 틱

매 프레임 액터를 업데이트하는 데 사용되는 Tick, 틱 시스템에 대한 설명입니다.

Windows
MacOS
Linux

Tick, 틱이란 액터나 컴포넌트에 일정 간격, 보통 한 프레임에 한 번 코드 조각 또는 블루프린트 스크립트를 실행시키는 것을 말합니다. 게임 액터와 컴포넌트 서로끼리 또는 엔진에서 이루어지는 프레임 단위 태스크를 기준으로 한 상대적 틱 순서에 대한 이해는, 한 프레임 뒤쳐지는 문제를 피하기 위해서 뿐만 아니라, 게임 실행에 있어서의 일관성을 확보하는 데도 필수적입니다. 액터와 컴포넌트 틱 주기는 매 프레임으로, 또는 최소 시간 간격으로 설정할 수도, 아니면 아예 안할 수도 있습니다. 추가로 엔진의 프레임 단위 업데이트 루프 내 다른 페이즈와도 같은 그룹으로 묶어, 특정 틱이 완료될 때까지 기다린 이후 시작하도록 개별적으로 명령을 내릴 수도 있습니다.

틱 그룹

액터와 컴포넌트의 틱 주기는, 최소 틱 간격을 지정하지 않은 이상 한 프레임에 한 번입니다. 틱 발생은 틱 그룹에 따라 이루어지며, 틱 그룹은 코드 또는 블루프린트에서 할당할 수 있습니다. 액터 또는 컴포넌트의 틱 그룹은, 주로 물리 시뮬레이션과 같은 다른 엔진내 프레임 프로세스 기준 프레임 내 틱 발생 시점을 결정하는 데 사용됩니다. 각 틱 그룹은 그에 할당된 모든 액터와 컴포넌트 틱이 완료된 이후에야 다음 틱 그룹을 시작합니다. 틱 그룹에 더해, 액터나 컴포넌트는 틱 종속성을 설정할 수 있는데, 다른 액터나 컴포넌트의 틱 함수가 완료되기 전까지 틱이 일어나지 않도록 하는 것입니다. 틱 그룹과 틱 종속성은 게임 내 물리 기반 동작과의 어우러짐이나, 다수의 액터 또는 컴포넌트가 연관된 순차적 게임플레이 동작이 어색하지 않도록 하는 데 있어서 매우 중요할 수 있습니다.

게임플레이 용도로 사용할 수 있는 틱 그룹은 다음과 같으며, 프레임 도중의 실행순서 순으로 각 그룹의 구체적인 의미와 컨텍스트를 곁들였습니다:

틱 그룹 순서

틱 그룹

엔진 동작

TG_PrePhysics

물리 이전 - 프레임 시작입니다.

TG_DuringPhysics

물리 도중 - 이 단계에 도달할 시점이면 물리 시뮬레이션이 시작된 것입니다. 이 그룹 틱 도중 언제든지, 또는 모든 그룹 멤버의 틱 완료 이후, 시뮬레이션을 완료하여 엔진의 물리 데이터를 업데이트할 수 있습니다.

TG_PostPhysics

물리 이후 - 물리 시뮬레이션이 끝나 이 단계 시작 시점에서는 엔진이 현재 프레임 데이터를 사용합니다.

n/a

잠복성 동작, 월드 타이머 매니저 틱, 카메라 업데이트, 레벨 스트리밍 볼륨과 스트리밍 작업 업데이트를 처리합니다.

TG_PostUpdateWork

n/a

n/a

프레임 전반에 생성된 액터의 유예식 스폰을 처리합니다. 프레임과 렌더를 마칩니다.

TG_PrePhysics

  • 액터가 물리 기반 어태치먼트를 포함해서 물리 오브젝트와 상호작용할 의도가 있는 경우 사용하는 틱 그룹입니다.

  • 이 틱 도중의 물리 시뮬레이션 데이터는 한 프레임 전, 즉 지난 프레임 화면에 렌더링된 데이터입니다.

TG_DuringPhysics

  • 이는 물리 시뮬레이션과 동시에 실행되기에, 이번 틱 도중의 물리 데이터가 전 프레임에서 온 것인지 현재 프레임에서 온 것인지 알 수 없습니다. 물리 시뮬레이션은 이 틱 그룹 내 언제든 완료 가능하며, 그러한 사실을 나타내는 정보를 제공하지는 않습니다.

  • 물리 시뮬레이션 데이터가 현재 또는 한 프레임 전의 것일 수 있으므로, 이 틱 그룹은 물리 데이터와 상관 없는 로직이나, 한 프레임 늦어져도 상관없는 경우에만 사용할 것을 추천합니다. 흔한 경우라면 인벤토리 화면 업데이트 또는 미니맵 표시의 경우인데, 물리 데이터가 완전히 무관하거나, 한 프레임 정도 지연되서 표시되도 별 상관이 없기 때문입니다.

TG_PostPhysics

  • 이 프레임의 물리 시뮬레이션 결과는 이 틱 그룹 실행 시점에서 완료됩니다.

  • 이 그룹은 무기나 무브먼트 트레이스에 사용하기 좋은데, 모든 물리 오브젝트는 최종 위치인 것으로 알려져 있어 이 프레임이 렌더링될 때 그려질 것이기 때문입니다. 이는 슈팅 게임의 레이저 시야와 같은 것에 특히나 좋은데, 레이저 빔은 플레이어 총의 최종 위치에서 나오는 것처럼 보여야 하고, 한 프레임만 랙이 발생해도 매우 눈에 띄기 때문입니다.

TG_PostUpdateWork

  • TG_PostPhysics 이후 실행됩니다. 역사적으로 그 주요 기능은 파티클 시스템에 최후의 순간 정보를 물려주는 것이었습니다.

  • TG_PostUpdateWork 는 카메라 업데이트 이후에 일어납니다. 카메라가 정확히 향하고 있는 방향에 의존하는 이펙트가 있는 경우라면, 그러한 이펙트 제어를 위한 액터는 이 곳에 넣는 것이 좋습니다.

  • 프레임 내 완전 다른 모든 것 이후 실행시킬 게임 로직에 사용하기에도 좋은데, 격투 게임에서 같은 프레임에 서로를 잡으려 하는 두 캐릭터를 알아내려는 경우가 그렇습니다.

틱 종속성

AddTickPrerequisiteActorAddTickPrerequisiteComponent 함수는 액터와 컴포넌트 양쪽에 존재하며, 이 함수가 호출되는 액터 또는 컴포넌트는 지정된 다른 액터 또는 컴포넌트의 틱이 완료될 때까지 틱을 대기하도록 설정합니다. 한 프레임 내 거의 동시에 일어나지만, 하나의 액터 또는 컴포넌트에 다른 액터 또는 컴포넌트가 필요로 하는 데이터가 구성되는 경우에 특히나 유용합니다. 틱 그룹이 아닌 이 기능을 사용하는 이유라면, 액터가 같은 그룹에 있는 경우 다수의 액터가 병렬 업데이트될 수가 있기 때문입니다. 그 액터가 다른 하나 또는 두 액터에 개별 종속되어 있는 경우, 한 액터 그룹을 완전히 새로운 그룹으로 옮기지 않아도, 전체 그룹의 틱이 완료될 때까지 기다릴 필요가 없습니다.

예제

틱 그룹 / 틱 종속성 사용 예

위 틱 그룹 각각에 대한 사용 예로, 플레이어가 어떤 애니메이션 액터를 조종하는데, 여기서 레이저가 발사되어 맞는 지점에 특수한 타기팅 레티큘 액터가 배치되는 게임이 있다고 상상해 봅시다. 레이저가 특정 유형의 대상 오브젝트에 머물러 있는 한 특수한 미터기가 채워지며, HUD 액터가 그 미터기를 화면상에 표시합니다.

플레이어의 애니메이션 액터는 TG_PrePhysics 에서 애니메이션 및 이동될 것입니다. 물리 시뮬레이션 오브젝트가 제대로 따라가며 상호작용하기 위해서는, 물리 이전에 애니메이션이 일어나야 합니다.

HUD 는 어느 틱 그룹에서 업데이트해도 되지만, 두 가지 이유로 TG_DuringPhysics 가 좋습니다. 첫째, TG_DuringPhysics 는 게임의 물리 시뮬레이션과 직접 상호작용하지도, 그 데이터를 사용하지도 않기 때문입니다. 둘째, 물리 시뮬레이션이 HUD 업데이트 완료를 대기하도록 할 필요도 없고, HUD 가 물리 시뮬레이션 완료를 대기하도록 할 필요가 없기 때문에 좋습니다. 참고로 HUD 는 게임에 한 프레임 뒤쳐집니다. 즉 이 프레임에 타깃 오브젝트를 조준하는 것은 다음 프레임까지 미터기에 반영되지 않습니다.

레티큘 액터 업데이트는 TG_PostPhysics 에서 일어납니다. 이런 식으로 레티큘은 프레임 끝에 렌더링되는 씬을 대상으로 트레이싱한다는 것을 알기에, 의도한 대로 오브젝트의 표면 위에 정확히 나타날 것을 압니다. 타깃 오브젝트의 올바른 위치를 기반으로 하여 미터기 값을 조정할 것이라는 것도 압니다.

마지막으로 TG_PostUpdateWork 에서, 레이저 파티클 이펙트를 조준 액터와 레티큘 양쪽의 최종 위치를 가지고 업데이트됩니다.

틱 종속성은 TG_PostUpdateWork 필요를 없애기 위해 사용할 수 있습니다. 레이저 파티클은 레티큘 액터와 함께 TG_PostPhysics 에 넣을 수 있는데, 틱 종속성을 사용하여 레티큘이 틱을 해도 괜찮겠다 싶을 때만 레티큘 위치를 가지고 레이저를 업데이트시키는 것입니다. 레티큘에 대한 레이저의 틱 종속성을 설정함으로써, 레이저 업데이트가 너무 일찍 일어나지 않게, 게다가 관련도 없는 다른 물리 이후 틱을 대기할 필요도 없게 만들 수 있습니다. 레이저를 다른 틱 그룹으로 이동시키는 것 보다 효율적일 수 있습니다.

틱 종속성의 덕을 보지 못할 경우의 예를 들자면, 레티큘 자체는 조준 액터에 대해서 틱 종속적일 필요는 없습니다. 물론 조준 액터의 틱이 완료되어야 레티큘 액터의 틱이 가능하기는 하지만, 종속적일 필요가 없는 이유라면 레티큘은 물리 이후에 있는 반면, 조준 액터는 물리 이전에 있기 때문입니다. 다른 틱 그룹에 있기에 항상 그룹 자체 순서대로의 실행을 보장받을 수 있습니다. 각 틱 그룹은 그 모든 액터와 컴포넌트 틱을 마친 이후에야 다른 틱 그룹이 시작되기 때문입니다.

액터 스폰

BeginPlay 에서, 액터는 주요 틱 함수와 그 컴포넌트의 틱 함수를 엔진에 등록합니다. 액터의 틱 함수는 특정 틱 그룹에서 실행되도록 설정하거나, 완전히 비활성화시킬 수도 있는데, PrimaryActorTick 멤버를 통해서입니다. 이는 일반적으로 생성자 안에서 BeginPlay 호출 전 데이터가 제대로 설정되었는지를 확인하기 위해 이루어집니다. 자주 사용되는 코드는 다음과 같습니다:

PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bTickEvenWhenPaused = true;
PrimaryActorTick.TickGroup = TG_PrePhysics;

컴포넌트 틱

액터를 각기 다른 틱 그룹으로 분리할 수 있듯이, 컴포넌트도 마찬가지입니다. 기존에는, 액터가 틱 도중 그 모든 컴포넌트에 틱을 적용했습니다. 이 부분은 지금도 여전하나, 다른 그룹에서 틱을 적용해야 하는 컴포넌트는 별도의 틱 시기를 관리하는 리스트에 추가됩니다. 컴포넌트는 액터의 틱 그룹을 나눌 때와 같은 범주로 틱 그룹을 나눕니다. 컴포넌트의 틱 구조는 액터가 사용하는 것과 이름은 다르지만, 같은 식으로 작동합니다:

PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bTickEvenWhenPaused = true;
PrimaryComponentTick.TickGroup = TG_PrePhysics;

PrimaryActorTick 은 액터의 Tick() 함수를 사용하는 반면, PrimaryComponentTick 은 액터 컴포넌트의 TickComponent() 함수를 사용한다는 점, 기억해 주시기 바랍니다.

고급 틱 함수 기능

액터나 컴포넌트에 대한 기본 틱 함수는 AActor::SetActorTickEnabledUActorComponent::SetComponentTickEnabled 함수로 게임 도중 활성화 또는 비활성화시킬 수 있습니다. 추가로 액터나 컴포넌트는 다수의 틱 함수를 가질 수 있습니다. FTickFunction 를 상속하는 구조체를 만들고 ExecuteTickDiagnosticMessage 함수를 덮어쓰면 됩니다. 직접 구조체를 만들어 보기 전, 액터와 컴포넌트의 기본 틱 함수 구조체가 참고하기에 좋은 예인데, EngineBaseTypes.h 에서 FActorTickFunctionFComponentTickFunction 이름 아래에서 찾을 수 있습니다.

액터나 컴포넌트에 별도의 틱 함수 구조체를 추가하고나면, 보통 소유 클래스의 생성자에서 초기화 가능합니다. 틱 함수의 활성화와 등록을 위해 가장 흔한 방법은 AActor::RegisterActorTickFunctions 를 덮어쓰고, 틱 함수 구조체의 SetTickFunctionEnable 호출을 추가한 뒤, 소유 액터의 레벨을 인수로 하여 RegisterTickFunction 호출을 하면 됩니다. 이 프로세스로 생성된 액터나 컴포넌트는, 다른 틱 그룹에서의 틱이나 틱 함수별 개별 틱 종속성을 포함해서, 여러 번 틱이 가능합니다. 틱 종속성을 수동 설정하려면, 종속되게 만들고자 하는 틱 함수 구조체에서 AddPrerequisite 을 호출한 뒤, 종속성으로 사용하고자 하는 틱 함수 구조체를 전달해 주면 됩니다.

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

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

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

네이버 카페
공식 포럼