공부/UE

[UE] AttributeSet을 생성만 해줘도 자동으로 ASC가 인식하는 이유

sudo 2025. 9. 20. 17:41
반응형

ChatGPT에게 이런식으로 CDO 영역에 Actor가 AttributeSet를 생성만 해줬는데 어떻게 ASC가 이를 인식하고 적용한 지 물어봤고 아래는 그에 대한 답변이다

 

좋은 포인트 짚으셨어요 👍
UAbilitySystemComponent::InitializeComponent 시점에서 AttributeSet들이 자동으로 ASC(AbilitySystemComponent)에 붙는 이유를 단계별로 설명드릴게요.


1. AttributeSet은 UObject

UAttributeSet은 UObject 기반이라서, 보통 UAbilitySystemComponent의 DefaultSubobject 또는 Owner의 Subobject로 만들어집니다.

즉, ASC가 소유한 액터(보통 ACharacter, AActor 등)에 CreateDefaultSubobject<UAttributeSet_XXX>(TEXT("AttributeSetName")) 식으로 멤버 선언해두면, 그 AttributeSet은 액터가 생성될 때 이미 인스턴스화되어 있고, Owner의 ChildObjects에 들어갑니다.


2. ASC의 InitializeComponent 동작

UAbilitySystemComponent::InitializeComponent() 내부에서는 대략 이런 로직을 탑니다:

  1. GetOwner() → ASC가 붙은 액터를 가져옴
  2. 액터의 ChildObjects(Subobjects) 를 순회
  3. 그 중에서 UAttributeSet을 상속한 애들을 모두 찾아서 SpawnedAttributes 배열에 등록

즉, 내가 따로 AddAttributeSet을 호출하지 않아도, 멤버 변수로 선언한 AttributeSet이 이미 Owner의 Subobject 트리에 들어 있어서 ASC가 그것을 스캔하는 구조예요.

3. 왜 ChildObjects에 들어가 있나?

UCLASS 안에서 이렇게 했다고 가정해봅시다:

 
UPROPERTY() UAttributeSet_Health* HealthSet;

생성자에서:

 
HealthSet = CreateDefaultSubobject<UAttributeSet_Health>(TEXT("HealthSet"));
  • 이렇게 하면 HealthSet은 Owner 액터의 DefaultSubobject가 됩니다.
  • 언리얼 엔진은 CreateDefaultSubobject로 만든 것들을 자동으로 ChildObjects에 넣어줍니다.
  • 그 상태로 BeginPlay 전에 ASC 초기화가 돌면서 ASC가 “아 이 액터에 AttributeSet 있네?” 하고 등록하는 것.

4. 정리

  • ASC::InitializeComponent는 Owner 액터의 Subobject(ChildObjects)를 스캔해서 UAttributeSet들을 SpawnedAttributes에 추가한다.
  • 내가 ASC->AddAttributeSet() 같은 걸 호출하지 않아도 되는 이유는, 액터 생성자에서 CreateDefaultSubobject<UAttributeSet>로 만든 AttributeSet들이 자동으로 ChildObjects에 들어가기 때문.
  • 그래서 ASC가 알아서 찾아내서 등록해준다.

 

실제로 찾아보니 UAbilitySystemComponent::InitializeComponent 함수에서 OwnerActor의 자식들을 다 찾아서 UAttributeSet 타입 객체를 전부 등록해주고 있었다

* GetObjectsWithOuter는 1번째 인자(여기선 ASC의 Owner)의 자식들을 TArray에 담아서 가져오는 함수이다

반응형