Good day!
I need help. I just can’t figure out the problem of automatically deleting an uobject from actor component.
Recreation steps:
- Created a pawn.
- Created a component.
- Created an uobject.
- c++ Create and store TestActorComponent int the pawn. Marked it as UPROPERTY().
- c++ Create and store my uobject in the component. Marked it as UPROPERTY().
- c++ Override BeginDestroy() function in the my uobject and add Log function to it
- After starting PIE, after a while, the uobject self-deletes. I can see it in the logs.
There is some garbage collecting action i think.
But I just can’t understand why. All pointers is marked as UPROPERTY(). So why it deletes them? And how to prevent them from deleting? Maybe it is a bug?
I tried to use AddToRoot() function. It helped but after stopping PIE, Editor crashes every time.
Also if i add component to pawn through blueprint than don’t delete self.
Here is code example:
////////////////////////////////////////////////////////////////////
// MyPawn.h
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Components")
UTestActorComponent* TestActorComponent;
////////////////////////////////////////////////////////////////////
//MyPawn.cpp
AMyPawn::AMyPawn()
{
TestActorComponent = CreateDefaultSubobject(TEXT("TestActorComponent"));
}
///////////////////////////////////////////////////////////////////
//TestActorComponent.h
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UGS_API UTestActorComponent : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UTestActorComponent();
private:
UPROPERTY()
UUgsMyObject* MyObject;
};
//////////////////////////////////////////////////////////////////////////////
// TestActorComponent.cpp
UTestActorComponent::UTestActorComponent()
{
MyObject = CreateDefaultSubobject(TEXT("MyObject"));
}
//////////////////////////////////////////////////////////////////
//MyObject.cpp
void UMyObject::BeginDestroy()
{
UE_LOG(LogTemp, Warning, TEXT("UMyObject:: UMyObject destroyed"));
Super::BeginDestroy();
}
I believe that if your object is not part of the root set it will be destroyed during garbage collection. After creating your object you can call its AddToRoot() function to add it to the root set and prevent it being garbage collected.
MyObject = CreateDefaultSubobject(TEXT("MyObject"));
MyObject->AddToRoot();
I tried to do that. And it worked. But if you stop PIE editor crashes momentary. Maybe i could call RemoveFomRoot() function somehow, but where do I should call it? C++ destructor not called in UE4. And BeginDestroy() funcion is called much later than it needed to prevent crash of editor.
I believe that you can call the object’s RemoveFromRoot() function to release it and allow it to be garbage collected normally which should prevent the crash.
There is problem I tried to call RemoveFromRoot function in the BeginDestroy function and in the c++destructor. But it seem never called and editor crashes again. Also according ue4 documentation, marking pointer variable as UPROPERTY should make reference to root set automatically. But I checked it never happened. So I still searching how fix this issue.
Is your UUgsMyObject is a component? If it’s just an uboject try calling NewObject instead.
No, this is not a component. I tried both options (CreateDefaultSubobject() and NewObject()). It does’t work. From what I was able to figure out with, the problem occurs when trying to create a new object inside a component’s constructor. Then the new sub object cannot add itself to the rootset because its owner has not yet managed to initialize itself. If you add a sub object to the component’s constructor, then the UE4 reflection system will overwrite the UPROPERY pointer and set it to zero. I mean, earlier when the FObjectInitializer was used in construction you could call the parent constructor before creating a new object. This does not apply to actors, because they hidden use the FObjectInitializer in the constructor (it is used to display components in blueprints ). Therefore, you can add components in the constructor of the actor. But in a component itself, sub objects can only be added to the “BeginPlay() ” functions . Otherwise, they will self-destruct.
This is currently the best solution i could find. But I think that this is still not how the behavior of the system is described in the documentation
I believe this is because the instance of the object that got destroyed is NOT the one that you created during runtime.
Try log the object name when you create it and in the BeginDestroy() function. See if they are the same one.
Or, you could set a timer, call a function a few seconds later to check whether the object of your component is still valid after you see a BeginDestory() log.
However I am a newbee myself, I can’t explain clearly why there is other instance that will be destroyed by the engine.