How to reproduce:
- Create a new c++ project, Basic code (i called it GarbageCollectorTest).
- Create a new GameState based class (called it MyGameState)
- Create a new UObject based class (called it MyObject)
- Modify the code as below
- Compile as Development Editor, set the game mode as GarbageCollectorTestGameMode
- Run it, open the console, and use the command TestMyObject
Code:
MyGameState.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "GameFramework/GameState.h"
#include "MyGameState.generated.h"
/**
*
*/
UCLASS()
class GARBAGECOLLECTORTEST_API AMyGameState : public AGameState
{
GENERATED_BODY()
public:
UFUNCTION(Exec)
void TestMyObject();
protected:
#if !UE_BUILD_SHIPPING
UPROPERTY()
class UMyObject* MyObject;
#endif
};
MyGameState.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "GarbageCollectorTest.h"
#include "MyGameState.h"
#include "MyObject.h"
void AMyGameState::TestMyObject()
{
#if !UE_BUILD_SHIPPING
MyObject = NewObject<UMyObject>(this, UMyObject::StaticClass());
UE_LOG(LogTemp, Error, TEXT("MyObject created: %s"), (MyObject != nullptr) ? TEXT("TRUE") : TEXT("FALSE"));
#endif
}
MyObject.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Object.h"
#include "MyObject.generated.h"
/**
*
*/
UCLASS()
class GARBAGECOLLECTORTEST_API UMyObject : public UObject
{
GENERATED_BODY()
virtual void BeginDestroy() override;
};
MyObject.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "GarbageCollectorTest.h"
#include "MyObject.h"
void UMyObject::BeginDestroy()
{
Super::BeginDestroy();
UE_LOG(LogTemp, Error, TEXT("MyObject destroyed"));
}
GarbageCollectorTestGameMode.h
// Copyright 2015 DESTINYbit. All Rights Reserved.
#pragma once
#include "GameFramework/GameMode.h"
#include "GarbageCollectorTestGameMode.generated.h"
/**
*
*/
UCLASS()
class GARBAGECOLLECTORTEST_API AGarbageCollectorTestGameMode : public AGameMode
{
GENERATED_BODY()
public:
AGarbageCollectorTestGameMode(const FObjectInitializer& ObjectInitializer);
};
GarbageCollectorTestGameMode.cpp
// Copyright 2015 DESTINYbit. All Rights Reserved.
#include "GarbageCollectorTest.h"
#include "GarbageCollectorTestGameMode.h"
#include "MyGameState.h"
AGarbageCollectorTestGameMode::AGarbageCollectorTestGameMode(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
GameStateClass = AMyGameState::StaticClass();
}
Resulting behaviour:
MyObject gets garbage collected after some random time, as we can see in the log:
[2015.05.03-17.42.39:499][383]PIE: Info Play in editor start time for /Temp/UEDPIE_0_Untitled_1 -0.239
[2015.05.03-17.42.42:434][732]Cmd: TestMyObject
[2015.05.03-17.42.42:434][732]LogTemp:Error: MyObject created: TRUE
[2015.05.03-17.43.39:438][495]LogTemp:Error: MyObject destroyed
The object will not be GC’ed, correctly, if we remove the “#if !UE_BUILD_SHIPPING” from the UPROPERTY declaration.
Expected behaviour:
MyObject should not be GCed until we set the pointer to NULL.
This is not a critical issue, i encountered it while working on some debug code, but it is strange.
Hope this helps,
Simone Daminato.