배움 저장소

[UE4] Unreal Property System (Reflection) 본문

Dev/Unreal Engine4

[UE4] Unreal Property System (Reflection)

시옷지읏 2021. 11. 2. 13:04
 

Unreal Property System (Reflection)

Reflection is the ability of a program to examine itself at runtime. This is hugely useful and is a foundational technology of the Unreal engine, powering many systems such as detail panels in the editor, serialization, garbage collection, network replicat

www.unrealengine.com

 

C++ 코드와 Unreal Edtior, BluePrint와 상호작용하면 코드에서 만든 변수를 에디터에서 수정할 수 있고, BluePrint에서 C++코드의 변수와 함수를 불러올 수 있다. Unreal에서는 Relfection을 사용하여 이러한 기능을 사용한다. 이러한 Reflection을 사용하려면 다음 Header를 추가해야한다.

#include "FileName.generated.h"

이 헤더를 추가했을 때 UENUM(), UCLASS(), USTRUCT(), UFUNCTION(), UPROPERTY() 매크로를 사용할 수 있다. 각 매크로는 그에 맞는 변수를 가지고 있어 사용자가 원하는 바에 따라 코드와 에디터가 상호작용하게 만든다.

 

예제를 가져오면 다음과 같다. RTS게임의 예제이다.

#include "StrategyTypes.h"
#include "StrategyChar.generated.h"

UCLASS(Abstract)

class AStrategyChar : public ACharacter, public IStrategyTeamInterface
{

	GENERATED_UCLASS_BODY()

	/** How many resources this pawn is worth when it dies. */
	UPROPERTY(EditAnywhere, Category=Pawn)
	int32 ResourcesToGather;

	/** set attachment for weapon slot */
	UFUNCTION(BlueprintCallable, Category=Attachment)
	void SetWeaponAttachment(class UStrategyAttachment* Weapon);

	UFUNCTION(BlueprintCallable, Category=Attachment)
	bool IsWeaponAttached();

	protected:

	/** melee anim */
	UPROPERTY(EditDefaultsOnly, Category=Pawn)
	UAnimMontage* MeleeAnim;

	/** Armor attachment slot */
	UPROPERTY()
	UStrategyAttachment* ArmorSlot;

	/** team number */
	uint8 MyTeamNum;

	[more code omitted]
};

위 예제에서 사용된 여러 Reflection Data를 소개한다.

UField
	UStruct
		UClass (C++ class)
		UScriptStruct (C++ struct)
		UFunction (C++ function)

	UEnum (C++ enumeration)

	UProperty (C++ member variable or function parameter)

위 매크로를 사용할 때 주의할점은

1. C++에서 사용하는 struct에 Reflection을 적용할 때 UStruct 매크로를 사용하면 안된다. UStruct는 위에 나타나있는 타입을 모두 포함하는 상위 개념이다. 실제 C++에서 사용하는  struct는 UScriptStruct로 사용해야한다.

 

2. Reflection 매크로를 사용하지 않은 UObject는 Garbage Collector와 상호작용하지 못한다. Memory Leak가 일어나지 않게 하려면 Reflection 매크로를 사용해주자.

 

3.

UClass() 매크로를 사용할 때 객체 내부에 꼭 GENERATED_UCLASS_BODY()를 정의해주자. 내부에 정의할 이 함수는 UCLass가 사용할 수 있는 여러 함수와 변수를 자동으로 만들어준다.

 만약 사용자가 코드 내부에서 특정 UClass 혹은 UScriptStruct의 인스턴스를 가져오고 싶다고 하자. 다음과 같은 코드를 사용하면된다.

// get the UClass for a reflected C++ type
UTypeName::StaticClass()

// get the UScriptStruct for a reflected C++ type
FTypeName::StaticStruct()

// get the type for a UObject instance
Instance->GetClass() 
 
 // To iterate over all members of a UStruct, use a TFieldIterator:
for (TFieldIterator<UProperty> PropIt(GetClass()); PropIt; ++PropIt)
{
	UProperty* Property = *PropIt;
	// Do something with the property
}

 아래에 TFieldIterator는 해당 클래스를 순환할 수 있게 해준다. UProperty 대신에 UField를 사용하면 Property와 Function 모두 찾아볼 수 있다.

 

4. 해당 매크로는 각각의 Specifier를 가지고 있다. 필요한 것을 찾아 활용하면 된다.

https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/GameplayArchitecture/Properties/Specifiers/

https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/GameplayArchitecture/Classes/Specifiers/

https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/GameplayArchitecture/Functions/Specifiers/

https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/GameplayArchitecture/Structs/Specifiers/

 

 

봐도 모르겠다. 나중에 지식이 더 쌓였을 때 볼 내용

Limitations

UHT isn’t a real C++ parser. It understands a decent subset of the language and actively tries to skip any text that it can; only paying attention to reflected types, functions, and properties. However, some things can still confuse it, so you may have to reword something or wrap it in an #if CPP / #endif pair when adding a reflected type to an existing header. You should also avoid using #if/#ifdef (except for WITH_EDITOR and WITH_EDITORONLY_DATA) around any annotated properties or functions, since the generated code references them and will cause compile errors in any configuration where the define isn’t true.

Most common types work as expected, but the property system can’t represent all possible C++ types (notably only a few template types such as TArray and TSubclassOf are supported, and their template parameters cannot be nested types). UHT will give you a descriptive error message if you annotate a type that can’t be represented at runtime.

'Dev > Unreal Engine4' 카테고리의 다른 글

[UE4] Introduction to C++ Programming in UE4  (0) 2021.11.08
[UE4] Asset Manger and Soft Reference  (0) 2021.11.07
[UE4] Profiling and Optimization  (0) 2021.10.31
[UE4] UI 최적화  (0) 2021.10.30
[UE4] Programming KickStart  (0) 2021.10.28
Comments