[Unreal_C++_DarkSoul]#14_Actor Compnent 간 소통
객체의 Actor Component간 소통을 구현합니다.
Overview
- 문제
- 해결
- GetOwner() vs FindComponentByClass<T>()
#0. 문제
1. 문제
- GameObject 객체는 다양한 Actor Component를 가집니다(Mana 컴포넌트, Weapon 컴포넌트 등)
- Actor Compnent 간의 소통을 위해 각 컴포넌트는 BeginPlay() 정의부에서 GetOwner()를 통해 액터 객체를 가져와 서로의 컴포넌트에 대한 참조를 가져오는 방법을 사용합니다. 하지만, 각 컴포넌트의 초기화 완료 시점이 다르기 때문에, 아직 초기화되지 않은 컴포넌트의 참조를 가져오는 에러가 발생합니다.
- 이때, Tick(float DeltaTime) 함수 내에서 동일한 방법을 사용해 문제를 해결할 수 있습니다. 하지만, Tick() 함수는 게임 시작과 함께 매 프레임마다 호출되는 루프 함수이며, 게임 성능에 영향을 끼칩니다.
#1. 해결
1. 해결 방법
- 어떤 Actor Component 클래스의 BeginPlay() 내에서 Owner 객체의 또 다른 Actor Component의 참조를 가져오기 위해 우리는 FindComponentByClass 템플릿 함수를 활용합니다!
2. AGameObject::AGameObject()
AGameObject::AGameObject()
{
PrimaryActorTick.bCanEverTick = false;
StateComponent = CreateDefaultSubobject<UC_StateComponent>(TEXT("State Component"));
HealthComponent = CreateDefaultSubobject<UC_HealthComponent>(TEXT("Health Component"));
ManaComponent = CreateDefaultSubobject<UC_ManaComponent>(TEXT("Mana Component"));
StaminaComponent = CreateDefaultSubobject<UC_StaminaComponent>(TEXT("Stamina Component"));
WeaponComponent = CreateDefaultSubobject<UC_WeaponComponent>(TEXT("Weapon Component"));
VaultComponent = CreateDefaultSubobject<UC_VaultComponent>(TEXT("Vault Component"));
IKComponent = CreateDefaultSubobject<UC_IKComponent>(TEXT("IK Component"));
MontageComponent = CreateDefaultSubobject<UC_MontageComponent>(TEXT("Montage Component"));
RewardComponent = CreateDefaultSubobject<UC_RewardComponent>(TEXT("Reward Component"));
//...
}
Details
- GameObject 클래스의 생성사 내에서 다양한 액터 컴포넌트들을 생성하고 있습니다.
- 이 중 몇몇 컴포넌트들은 서로에 대한 참조를 필요로 합니다.
- 예를 들면, Mana 컴포넌트는 GameObject 객체가 어떤 Weapon의 스킬을 사용했는지 알 필요가 있습니다. 따라서, GameObject 객체의 스킬 사용 시 Mana 컴포넌트는 Weapon 컴포넌트에 대한 참조가 필요합니다.
3. UC_ManaComponent::BeginPlay()
void UC_ManaComponent::BeginPlay()
{
Super::BeginPlay();
AActor* OwnerActor = GetOwner();
UC_WeaponComponent* OwnerWeaponComp = OwnerActor->FindComponentByClass<UC_WeaponComponent>();
CheckTrue(!OwnerActor || !OwnerWeaponComp);
OwnerWeaponComp->OnRequireMana.BindUFunction(this, "StartAttackSkillCoolTime");
//...
}
Details
- Mana 컴포넌트 클래스의 BeginPlay() 함수 정의부에서 Weapon 컴포넌트의 OnRequireMana 델리게이트에 동적 바인딩을 수행합니다.
- 이때, FindComponentByClass 템플릿 함수를 통해 액터 객체의 컴포넌트에 대한 초기화 여부와 상관없이 컴포넌트드를 가져올 수 있어 에러를 발생시키지 않습니다.
- FindComponentByClass 템플릿 함수를 통해 GameObject 객체의 또 다른 액터 컴포넌트, Weapon 컴포넌트를 가져와 Weapon Component 클래스에서 선언한 OnRequireMana 델리게이트에 StartAttackSkillCoolTime() 함수를 동적 바인딩 할 수 있습니다.
#2. GetOwner() vs FindComponentByClass <T>()
4. GetOwner() vs FindComponentByClass <T>()
- GetOwner()를 통해 Owner 액터 객체를 가져와 GetWeaponComponent()를 통해 Weapon Component에 대한 참조를 가져올 수 있습니다. FindComponentByClass 템플릿 함수를 통해 동일한 작업을 수행할 수 있습니다.
- 액터 컴포넌트의 BeginPlay() 내에서 GetOwner()와 Getter 함수를 통해 또 다른 액터 컴포넌트 객체의 참조를 가져오는 방법은 검색 대상이 제한되기 때문에 성능이 좋습니다. 그러나, 해당 컴포넌트의 초기화 작업 이전에 가져오려고 하는 경우, Null 포인터 오류가 발생할 가능성이 있습니다.
- 액터 컴포넌트의 BeginPlay() 내에서 FindComponentByClass 템플릿 함수를 통해 동일한 작업을 수행하며 컴포넌트의 초기화 여부와 상관없이 해당 컴포넌트를 가져올 수 있습니다. 하지만, FindComponentByClass 템플릿 함수는 Owner 액터 객체가 가지고 있는 모든 컴포넌트를 대상으로 검색을 수행하므로, 성능 저하가 우려됩니다!
'개인프로젝트' 카테고리의 다른 글
[Unreal_C++_DarkSoul]#16_문제 해결, 런 타임 AI 실행 여부 (0) | 2023.05.27 |
---|---|
[Unreal_C++_DarkSoul]#15_문제 해결, Data Table 로드 함수 (1) | 2023.05.08 |
[Unreal_C++_DarkSoul]#13_기능 구현, Impact Effect (0) | 2023.02.05 |
[Unreal_C++_DarkSoul]#12_문제 해결, Targeting 회전 속도 (0) | 2022.12.25 |
[Unreal_C++_DarkSoul]#11_기능 구현, Parkour(Vaulting) (0) | 2022.12.25 |