简体   繁体   中英

How to properly use multiple destructors in UE4

In my game I am creating some big class, which store references to smaller classes, which store some references too. And during gameplay I need to recreate this big class with all its dependencies by destroying it and making new one.

It's creation looks like that:

ABigClass::ABigClass()
{
    UE_LOG(LogTemp, Warning, TEXT("BigClass created"));
    SmallClass1 = NewObject<ASmallClass>();
    SmallClass2 = NewObject<ASmallClass>();
    ......
}

And it works. Now I want to destroy and re create it by calling from some function

BigClass->~ABigClass();
BigClass= NewObject<ABigClass>();

which destroys BigClass and creates new one with new small classes, the problem is, that old small classes are still in memory, I can see it by logging their destructors.

So I try to make such destructor for Big Class

ABigClass::~ABigClass()
{
    SmallClass1->~ASmallClass();
    SmallClass2->~ASmallClass();
    ......
    UE_LOG(LogTemp, Warning, TEXT("BigClass destroyed"));
}

SmallClass is inherited from other class, which have its own constructor and destructor, but I do not call it anywhere.

Sometimes it works, but mostly causes UE editor to crash when code compiled, or when game starsted/stopped.

Probably there is some more common way to do what I want to do? Or some validation which will prevent it from crash?

Please help.

Don't manually call a destructor. Replace

SmallClass1->~ASmallClass();
SmallClass2->~ASmallClass();

with either

delete SmallClass1;
SmallClass1 = nullptr;

or by nothing if those type are ref-counted by unreal in some fashion (likely).

Finally I found the way to do this. First, I needed to get rid of all UPROPERTYs, related to classes, which I am going to destroy, except UPROPERTYs in a class, which controls their creation and destruction. If I need to expose these classes to blueprints somewhere else, it can be done with BlueprintCallable getter and setter functions.

Then I needed to calm down UE's garbage collector, which destroy objects on hot reload and on game shutdown in random order, ignoring my destructor hierarchy, which results in attempt to destroy already destroyed object and crash. So before doing something in destructor with other objects, I need to check if there is something to destroy, adding IsValidLowLevel() check.

And instead of delete keyword it is better to use DestructItem() function, it seems to be more garbage collector-friendly in many ways.

Also, I did not found a way to safely destroy objects, which are spawned in level. Probably because they are referenced somewhere else, but I dont know where, but since they are lowest level in my hierarchy, i can just Destroy() them in the world, and do not bother when exactly they will disappear from memory by garbage collector's will.

Anyway, I ended up with following code:

void AGameModeBase::ResetGame()
{
    if (BigClass->IsValidLowLevel()) {
        DestructItem(BigClass);
        BigClass= nullptr;
        BigClass= NewObject<ABigClass>();   
        UE_LOG(LogTemp, Warning, TEXT("Bigclass recreated"));
    }
}

ABigClass::~ABigClass()
{
    if (SmallClass1) {
        if (SmallClass->IsValidLowLevel())
        {
            DestructItem(SmallClass1);  
        }
        SmallClass1 = nullptr;
    }   
    if (SmallClass2) {
        if (SmallClass->IsValidLowLevel())
        {
            DestructItem(SmallClass2);  
        }
        SmallClass2 = nullptr;
    }   
    ...
    UE_LOG(LogTemp, Warning, TEXT("BigClass destroyed"));
}

ASmallClass::~ASmallClass()
{
    for (ATinyClass* q : TinyClasses)
    {
        if (q->IsValidLowLevel())
        {
            q->Destroy();
        }
    }
    TinyClasses = {};

    UE_LOG(LogTemp, Warning, TEXT("SmallClass destroyed"));
}

And no crashes. Probably someone will find it useful in cases it is needed to clear game lever from hierarchy of objects without fully reloading it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM