본문으로 건너뛰기

UFUNCTION과 함수 지정자

Summary

UFUNCTION은 함수를 Unreal의 호출 표면에 올리는 선언이다. 괄호 안에 무엇을 넣는지에 따라 블루프린트 노드가 될 수도 있고, 서버 RPC가 될 수도 있고, 에디터 버튼이나 이벤트 확장 지점이 될 수도 있다.

포함된 공식 주제

  • UFunctions

When You Use This

BlueprintCallable, BlueprintPure, Server, NetMulticast, BlueprintNativeEvent, CallInEditor가 어떻게 다른지 정리하고 싶을 때 읽는다.

Core Concept

UFUNCTION의 공통 형태는 아래처럼 읽으면 된다.

UFUNCTION([Function Specifiers], meta=(Metadata Specifiers))

function specifier는 호출 경로와 실행 규칙을 정하고, meta=(...)는 블루프린트 노드의 표시와 핀 동작을 조정한다. 특히 RPC와 BlueprintNativeEvent는 선언만으로 끝나지 않고 _Implementation 규칙까지 함께 따라온다.

Example

UFUNCTION(BlueprintCallable, Category = "Combat", meta = (DisplayName = "Apply Damage", Keywords = "hit damage attack"))
void ApplyDamage(int32 Amount);

UFUNCTION(Server, Reliable)
void ServerReload();

UFUNCTION(BlueprintNativeEvent, Category = "Interaction")
void Interact(AActor* InstigatorActor);

Explanation

첫 함수는 블루프린트에서 직접 호출할 공개 API고, 두 번째는 서버에서 실행되어야 하는 RPC이며, 세 번째는 C++ 기본 구현을 둘 수 있으면서 블루프린트가 덮어쓸 수 있는 이벤트다. 셋 모두 UFUNCTION이지만, 누가 호출하고 어디서 실행되며 어떤 보조 코드가 생성되는지가 완전히 다르다.

괄호 안을 읽는 순서

  1. 이 함수가 블루프린트에서 보이는지 본다. BlueprintCallable, BlueprintPure가 가장 먼저 보인다.
  2. 실행 위치가 네트워크와 연결되는지 본다. Server, Client, NetMulticast가 여기에 해당한다.
  3. 이벤트 확장 지점인지 본다. BlueprintImplementableEvent, BlueprintNativeEvent가 대표적이다.
  4. 에디터나 콘솔에서 특별히 호출되는지 본다. CallInEditor, Exec 같은 항목이다.
  5. 마지막으로 Categorymeta=(...)를 보고 블루프린트 노드 형태를 읽는다.

자주 쓰는 Function Specifier

specifier언제 쓰는가의미
BlueprintCallable블루프린트에서 직접 호출할 때실행 핀이 있는 함수 노드로 노출한다
BlueprintPure상태를 바꾸지 않는 조회 함수일 때실행 핀 없는 순수 함수 노드로 노출한다
BlueprintImplementableEventC++ 선언만 두고 블루프린트가 구현하게 할 때블루프린트 구현 지점을 만든다
BlueprintNativeEventC++ 기본 구현과 블루프린트 확장을 함께 허용할 때_Implementation 기반 기본 구현을 둔다
Server서버에서 실행되어야 할 때서버 RPC로 동작한다
Client특정 클라이언트에서 실행되어야 할 때클라이언트 RPC로 동작한다
NetMulticast서버 호출 후 모든 클라이언트에 전파할 때멀티캐스트 RPC로 동작한다
Reliable반드시 전달되어야 할 RPC일 때재전송을 보장하는 RPC로 표시한다
Unreliable자주 호출되지만 일부 손실을 감수할 수 있을 때가벼운 RPC로 사용한다
CallInEditor에디터에서 버튼처럼 실행하고 싶을 때디테일 패널에서 호출할 수 있다
Exec콘솔 명령으로 노출할 때특정 클래스 컨텍스트에서 콘솔 명령처럼 호출된다
BlueprintAuthorityOnly블루프린트에서는 권한 있는 측만 실행하게 할 때권한 없는 Blueprint 실행을 막는다

자주 쓰는 메타데이터

metadata언제 쓰는가의미
DisplayName="..."노드 이름을 더 읽기 좋게 바꿀 때블루프린트 표시 이름을 바꾼다
Keywords="..."검색어를 추가하고 싶을 때블루프린트 검색 편의성을 높인다
CompactNodeTitle="..."짧은 노드 제목이 필요할 때시각적으로 축약된 노드를 만든다
AutoCreateRefTerm="ParamName"참조 파라미터 기본값 노드를 덜 번거롭게 할 때입력 핀 연결이 없어도 임시 값을 만들어 준다
DefaultToSelf="ParamName"self를 기본 연결 대상으로 삼을 때블루프린트 사용성을 높인다
WorldContext="ParamName"월드 컨텍스트를 숨기고 자동 연결할 때함수 라이브러리 노드에서 자주 쓴다

_Implementation이 붙는 경우

BlueprintNativeEvent와 RPC는 선언만 보고 끝내면 안 된다. UHT가 별도 thunk와 구현 함수를 연결하므로, 실제 구현은 _Implementation 이름으로 작성한다.

void AMyCharacter::ServerReload_Implementation()
{
// 서버에서 실행될 실제 로직
}

void AInteractableActor::Interact_Implementation(AActor* InstigatorActor)
{
// BlueprintNativeEvent의 기본 C++ 구현
}

이 패턴은 일반 C++ 함수 선언과 가장 크게 다른 부분이다.

기존 C++와 다른 점

일반 C++ 함수는 호출 규칙을 주로 코드 흐름으로만 표현한다. Unreal C++ 함수는 선언부에서 호출 표면까지 함께 설명한다. 같은 void Reload()라도 UFUNCTION(Server, Reliable)가 붙으면 단순 멤버 함수가 아니라 네트워크 호출 규칙을 가진 엔진 함수가 된다.

Common Mistakes

  • BlueprintPure에 실제 상태 변경 로직을 넣는다.
  • RPC나 BlueprintNativeEvent에 필요한 _Implementation 규칙을 빠뜨린다.
  • Reliable을 모든 RPC에 습관적으로 붙인다.
  • UFUNCTION.cpp 정의부에서만 생각하고 헤더 선언부 규칙을 놓친다.