Hi
I have had a problem which was difficult to diagnose where a class I had derived from UObject attached to my GameState object was suddenly becoming invalid. The values stored within it suddenly became garbage.
The class was added as derived from UObejct through Editor > Add Code
The object was constructed in my GameState constructor using NewObject <T>
After overriding the BeginDestroy method on my UObject, this method is being called after an arbitrary amount of time even though my GameState object still has a valid reference to it.
Is this a defect or am I not correctly handling reference counter on my object?
EDIT:
GameMode class is defined thusly:
#pragma once
#include "SandboxGameMode.generated.h"
UCLASS(minimalapi)
class ASandboxGameMode : public AGameMode
{
GENERATED_UCLASS_BODY()
/** Specifies game time start date */
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category=Time)
FDateTime GameStartDateTime;
EGameModePlayState::Type GetCurrentPlayState() const;
// Overrides
virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override;
virtual void InitGameState() override;
virtual void Tick(float deltaSeconds) override;
private:
/** Manage current play state */
TEnumAsByte<EGameModePlayState::Type> m_currentPlayState;
};
The GameState is set in the GameMode constructor as:
GameStateClass = ASandboxGameState::StaticClass();
The GameState class is defined thusly
#pragma once
#include "GameFramework/GameState.h"
#include "DateTimeController.h"
#include "SandboxGameState.generated.h"
UCLASS()
class SANDBOX_API ASandboxGameState : public AGameState
{
GENERATED_UCLASS_BODY()
/** */
UFUNCTION(BlueprintCallable, Category = GameState)
FDateTimeState& GetDateTimeState();
void UpdateFromTick(float deltaSeconds);
virtual void BeginDestroy() override;
private:
/** */
UDateTimeController* m_dateTimeController;
};
DateTimeController is created as so in GameState constructor:
// Constructe Date and Time Controller for game
m_dateTimeController = NewObject<UDateTimeController>();
The DateTimeContoller is defined as follows
#pragma once
#include "Object.h"
#include "DateTimeController.generated.h"
UENUM(BlueprintType)
namespace EDayCycle
{
enum Type
{
None UMETA(DisplayName = "None"),
Dawn UMETA(DisplayName = "Dawn"),
Day UMETA(DisplayName = "Day"),
Dusk UMETA(DisplayName = "Dusk"),
Night UMETA(DisplayName = "Night")
};
}
/**
* Blueprint Integration Data Structure
*/
USTRUCT(BlueprintType)
struct FDateTimeState
{
GENERATED_USTRUCT_BODY()
/** Specifies the current cycle of the day */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Time)
TEnumAsByte<EDayCycle::Type> DayCycle;
/** Specifies current in game date and time */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Time)
FDateTime GameDateTime;
/** Specifies the current position for the sun */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Time)
FRotator SunDirection;
};
/**
*
*/
class SANDBOX_API UDateTimeController : public UObject
{
GENERATED_UCLASS_BODY()
/** Struct to maintain DateTime state */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Time)
FDateTimeState DateTimeInstance;
void UpdateFromTick(float deltaSeconds);
virtual void BeginDestroy() override;
private:
void UpdateSunPosition();
// Number of ticks in a day
static const int64 TICKS_PER_DAY;
// Number of ticks in a day
static const int64 TICKS_PER_HOUR;
// Number of ticks in a day
static const int32 TICKS_PER_SECOND;
};