언리얼로 작업하다보면 별도의 쓰레드를 생성해야 할 일이 있습니다. 다소 복잡한 연산을 수행한다던가, blocking함수를 사용한다던가 하는 이유로 언리얼 랜더링 쓰레드에 영향을 주지 않기 위함입니다. 예를 들어 소켓 통신을 위해 서버 소켓을 Listening 했을 경우 쓰레드가 블락되고, 언리얼 화면이 멈춥니다.
소켓에 관해선 다음에 정리하기로 하고, Thread 생성법을 정리합니다. 이번에도 문체가 다소 딱딱할 수 있습니다!
1. FRunnable
언리얼엔진은 c++ 를 사용하므로 c++ 11 표준인 #include <thread>를 사용해 Thread를 생성해도 되고, 래핑한 FThread를 사용해도 되지만 해당 아래 문서에도 나왔듯 대부분의 병렬 처리는 FRunnable을 사용하는 것이 바람직하다. Core 모듈이기 때문에 별도 모듈 추가는 필요하지 않다.
<FThread 문서>
<FRunnable 문서>
2. 헤더 추가
#include "CoreMinimal.h"
#include "HAL/Runnable.h"
#include "HAL/RunnableThread.h"
3. .h
class CUSTOMTHREAD_API/*1)*/ FCustomTherad: public FRunnable
{
public:
FCustomTherad();//Ctor
~FCustomTherad();
/* 2) */
static void Shutdown();
/* 쓰레드를 중지하고 완료시까지 기다린다. */
void EnsureCompletion();
// Begin FRunnable interface. 3)
virtual bool Init() override;
virtual uint32 Run() override;
virtual void Stop() override;
virtual void Exit() override;
// End FRunnable interface
private:
/* 2) */
static FCustomTherad*Instance;
/* 이 Runnable 객체를 실행하기 위한 스레드 */
FRunnableThread *Thread;
/* 쓰레드 중지할 때 사용. */
FThreadSafeCounter StopThreadCounter;
};
1) 생성한 프로젝트나 플러그인에 따라 달라질 수 있음.
2) 싱글톤으로 설계시 필요함.
3) 인터페이스 설명.
- Init()에서 false 반환 시 Run()이 호출되지 않음.(쓰레드 실행x)
멤버변수는 생성자에서 초기화 하나, 특정 조건에 의해 쓰레드 생성 여부를 결정하는 등에 사용하면 될 듯. - Run()은 한번 호출됨. Observer 등의 역할을 수행하는 쓰레드의 경우 While()문 사용.
정상 종료 시 return 0. 비정상 종료 시 return 1. - Stop()은 자동 호출되지 않음. 내가 원하는 타이밍에 호출하여 while문을 탈출하는 등으로 사용.
- Exit()는 Run() 리턴 시 호출됨. 멤버 포인터변수의 메모리 반환을 위해 사용하면 적합.
4. .cpp
#include "FCustomTherad.h"
#include "HAL/PlatformProcess.h"
FCustomTherad::FCustomTherad() :
Instance(nullptr),
Thread(nullptr),
StopThreadCounter(0)
{
Thread = FRunnableThread::Create(this, TEXT("FCustomTherad"), 0, TPri_BelowNormal); //windows default = 8mb for thread, could specify more
if (!Thread)
{
UE_LOG(LogTemp, Error, TEXT("Failed to create thread."));
}
}
FCustomTherad::~FCustomTherad()
{
if (Thread)
{
delete Thread;
Thread = nullptr;
}
}
void FCustomTherad::EnsureCompletion()
{
Stop();
if (Thread)
{
Thread->WaitForCompletion();
}
}
bool FCustomTherad::Init()
{
UE_LOG(LogTemp, Log, TEXT("thread started."));
return true;
}
uint32 FCustomTherad::Run()
{
if (!some_pointer)
{
UE_LOG(LogTemp, Error, TEXT("some_pointeris null, could not run the thread"));
return 1;
}
while (StopThreadCounter.GetValue() == 0)
{
// Do SomeThing
}
return 0;
}
void FCustomTherad::Stop()
{
StopThreadCounter.Increment();
}
void FCustomTherad::Exit()
{
UE_LOG(LogTemp, Log, TEXT("thread finished."));
}
끝.
참고문서
병렬 렌더링 개요
언리얼 엔진 4 의 병렬 렌더링에 대한 일반적 수준의 개요서입니다.
docs.unrealengine.com
스레디드 렌더링
스레디드 렌더러 작업을 하는 그래픽 프로그래머를 위한 정보입니다.
docs.unrealengine.com
'UnrealEngine' 카테고리의 다른 글
[UE] 포커스가 없을 때, 소리 재생 (0) | 2023.08.05 |
---|---|
UnrealEngine FSocket 통신 (0) | 2023.07.28 |
[UE4] 픽셀 스트리밍 ver_4.27(with. Android Build) (0) | 2023.07.08 |
[UE4] 4.27 AR 개발 (0) | 2023.06.25 |
[UE4] TextureRenderTarget. 이미지 버퍼로 텍스처 생성 (0) | 2023.01.24 |
댓글