#Confused about the need for AddWeakLamda

5 messages · Page 1 of 1 (latest)

mint thicket
#

I'm a little confused about the use of AddWeakLambda in UDebuffNiagaraComponent. My understanding from the course was that the weak lamda was necessary so that we don't increment the reference count of the character class and suppress garbage collection.

To monitor garbage collection I added a destructor to both the character base class and the debuff component. I was curious to see if the the following call that Stephen added would prevent garbage collection:

CombatInterface->GetOnDeathDelegate().AddDynamic(this, &UDebuffNiagaraComponent::OnOwnerDeath);

Everything destructed properly about 30 seconds after killing the character. All good.

I then tried using both AddWeakLamda and AddLamda for monitoring ASC late creation (outside if statement so it was always registering the callback). In both cases, both the component and character were garbage collected properly. So it seems that UE works properly even if you use a normal lamda instead of a weak one.

    if (CombatInterface)
    {
        CombatInterface->GetOnDeathDelegate().AddDynamic(this, &UDebuffNiagaraComponent::OnOwnerDeath);

        // Try adding a normal lambda
        CombatInterface->GetOnASCRegisteredDelegate().AddLambda([this](UAbilitySystemComponent* InASC)
        {
            InASC->RegisterGameplayTagEvent(DebuffTag, EGameplayTagEventType::NewOrRemoved).AddUObject(this, &UDebuffNiagaraComponent::DebuffTagChanged);
        });
    }

What am I missing here? Is my understanding of the purpose of AddWeakLamda incorrect?

#

Here was my destructor definition. Also added to UDebuffNiagaraComponent:

public:
    AAuraCharacterBase();
    virtual ~AAuraCharacterBase();

AAuraCharacterBase::~AAuraCharacterBase()
{
    UE_LOG(LogAura, Error, TEXT("Destructor called %s"), *GetActorLabel());
}

mint thicket
#

I suspect that actors commonly have circular references. The actor manages lifetime of components (like movement component), and the components often hold references to their parent (such as convenience parent or owner pointers). So it makes sense that when you explicitly destroy an actor, that the engine would need to free all these internal pointers to break the circular references and allow the reference count to go to zero. I've done something similar in the past and we called in "passivating the object". I haven't investigated deeply yet but this should apply to Lamdas as well. So the weak lamda for the component to the owner should not be, and clearly isn't, necessary.

mint thicket
#

I’m being imprecise mixing reference counting and garbage collection. Unreal uses the latter and most likely recognizes circular references within an object or object/component cluster. The only question here is whether these “internal” circular references with delegates are managed correctly in garbage collection. Likely?

mint thicket