Facility간 Link시 함수 호출 순서 문제
1. 문제
기존 On~방식의 함수만 사용했을때, 오버라이딩된 함수들에게 사용될 로직들의 순서를 적절하게 구성하는 것이 어려움. 이후 새로운 로직을 추가하거나 버그를 수정할 때 빠르게 파악하기 어려운 문제가 있다.
bool UPowerProviderComponent::TryLinkPowerConsumerFacility(APowerConsumerFacility* PowerConsumerFacility)
{
if (!IsLinked(PowerConsumerFacility))
{
LinkedPowerConsumerFacilities.AddUnique(PowerConsumerFacility);
// Provider와 Consumer가 연결되었을 때, Consumer측 로직은 OnLinkToPowerProvider를 통해 실행된다.
PowerConsumerFacility->OnLinkToPowerProvider(GetOwner());
return true;
}
return false;
}
구체적인 상황을 설명하자면, A->B->C 구조로 상속된 클래스의 On이라는 함수가 있다고 생각해 보자. 이 함수는 오버라이딩 되며 a, b, c라는 로직을 실행해야 하고 a->c->b의 순서로 실행되어야 한다. 이를 구현하면 아래와 같이 할 수 있다.
void A::On()
{
a;
}
void B::On()
{
b;
}
void C::On()
{
A::On();
c;
B::On();
}
구현 자체는 성공하였지만, 여러가지 문제가 있다.
- B클래스는 부모 클래스의 함수를 호출할 수 없다
- 언리얼 엔진 코드컨벤션에 적절한
Super키워드를 사용할 수 없다. - 이후 유지보수할 때 코드를 파악하기 어렵다
2. 시도
이를 해결하기 위해 On~이외에, Pre~, Post~ 함수를 추가하였다.
이 구조는 AActor클래스에 있는 함수방식을 차용했다.

bool UPowerProviderComponent::TryLinkPowerConsumerFacility(APowerConsumerFacility* PowerConsumerFacility)
{
if (!IsLinked(PowerConsumerFacility))
{
PowerConsumerFacility->PreLinkToPowerProvider();
LinkedPowerConsumerFacilities.AddUnique(PowerConsumerFacility);
PowerConsumerFacility->OnLinkToPowerProvider(GetOwner());
PowerConsumerFacility->PostLinkToPowerProvider();
return true;
}
return false;
}
void APowerConsumerFacility::PreLinkToPowerProvider_Implementation()
{
}
void APowerConsumerFacility::OnLinkToPowerProvider_Implementation(AActor* PowerProviderActor)
{
LinkedPowerProvider = PowerProviderActor;
LinkedPowerProviderInterface = Cast<IPowerProviderFacility>(LinkedPowerProvider);
check(LinkedPowerProviderInterface);
LinkedPowerProviderInterface->UpdatePowerUsage(PowerConsumption);
for (AFacilityAddon* Addon : ConnectedAddons)
{
Addon->OnFacilityLinkedToPowerProvider();
}
UpdatePowerWidgets();
// PowerWire 연결
TryConnectPowerWire(PowerProviderActor);
}
void APowerConsumerFacility::PostLinkToPowerProvider_Implementation()
{
}
void APowerConsumerFacility::PreTurnOn_Implementation()
{
}
void APowerConsumerFacility::PostTurnOn_Implementation()
{
TryLinkToNearByPowerProvider();
UpdatePowerWidgets();
}
void APowerConsumerFacility::PreTurnOff_Implementation()
{
}
void APowerConsumerFacility::PostTurnOff_Implementation()
{
UnlinkFromPowerProvider();
UpdatePowerWidgets();
}
PowerRelayFacility.cpp(APowerConsumerFacility의 하위 클래스)
void APowerRelayFacility::OnLinkToPowerProvider_Implementation(AActor* PowerProviderActor)
{
Super::OnLinkToPowerProvider_Implementation(PowerProviderActor);
check(IsLinkedToPowerProvider())
LinkedPowerProviderInterface->UpdatePowerUsage(PowerProviderComponent->GetCurrentPowerUsage());
PowerProviderComponent->LinkFacilitiesInPowerInfluenceArea();
}
void APowerRelayFacility::OnUnlinkFromPowerProvider_Implementation()
{
check(IsLinkedToPowerProvider());
LinkedPowerProviderInterface->UpdatePowerUsage(-PowerProviderComponent->GetCurrentPowerUsage());
Super::OnUnlinkFromPowerProvider_Implementation();
}
void APowerRelayFacility::PostUnlinkFromPowerProvider_Implementation()
{
PowerProviderComponent->UnlinkAllPowerConsumerFacility();
Super::PostUnlinkFromPowerProvider_Implementation();
}
void APowerRelayFacility::PreTurnOn_Implementation()
{
Super::PreTurnOn_Implementation();
}
void APowerRelayFacility::PostTurnOn_Implementation()
{
Super::PostTurnOn_Implementation();
PowerProviderComponent->LinkFacilitiesInPowerInfluenceArea();
}
void APowerRelayFacility::PreTurnOff_Implementation()
{
Super::PreTurnOff_Implementation();
}
void APowerRelayFacility::PostTurnOff_Implementation()
{
Super::PostTurnOff_Implementation();
}
3. 결과
- Chain방식으로 PowerConsumerFacility의 링크를 연결하고 끊는 과정에서 발생하는 함수 순서에 의한 버그 수정