1
\$\begingroup\$

I've made a class extending UObject to store player stats, and provide some static utility functions and variables. It gets instantiated in my PlayerController:

APuzzleProjectPlayerController::APuzzleProjectPlayerController() {
    playerStats = NewObject<UPlayerStats>();
    playerStats->setStrenght(4);
    playerStats->setSpeed(1);
    playerStats->setStamina(1);
}

Everything compiles fine and the game logic works perfectly except for the fact that after a while (1 or 2 minutes of gaming) the non-static private variables change their value.

In the following code I've added some Dummy variables just to make sure that nothing was accessing/changing them during execution. They are only accessed by GEngine->AddOnScreenDebugMessage to show their value.

UCLASS()
class PUZZLEPROJECT_API UPlayerStats : public UObject
{
    GENERATED_BODY()

    // Stats Const
    static const uint8 MIN_STAT_VALUE = 1;
    static const uint8 MAX_STAT_VALUE = 7;

    // Stamina Pool Const
    static const uint8 BASE_STAMINA_POOL = 199;
    static const uint8 STAMINA_POOL_STEP = 8;
    static const uint8 STAMINA_RECOVERY_VALUE = 3;

    // Stats
    uint8 strenght = 1; // Becomes 221
    uint8 speed = 1; // Becomes 221
    uint8 stamina = 1; // Becomes 221
    uint8 staminaPool = BASE_STAMINA_POOL; // Updated by a function, still unconsistent after a while since stamina dependent

    // These are never modified by my code, but get modified after a while like the Stats variables
    uint8 dummyA = 3; // Becomes 221
    const uint8 dummyB = 4; // Becomes 221
    int dummyC = 5; // Becomes -572662307
    const int dummyD = 6; // Becomes -572662307

    public:
    enum SpeedSteps {WALK, RUN, SPRINT};
    static const float TIMER_PRECISION;
    static const uint8 MIN_STAMINA_POOL = 0;
    static const uint8 MAX_STAMINA_POOL = 255;
    static const float DELTATIME_STAMINA_RECOVERY;
    static const float DELTATIME_STAMINA_LOSS;
    static const uint8 STAMINA_RUN_LOSS = 2;
    static const uint8 STAMINA_SPRINT_LOSS = 32;

    UPlayerStats();
    uint8 getStrenght();
    uint8 getSpeed();
    uint8 getStamina();
    uint8 getStaminaPool();
    static uint8 getStaminaDelta(SpeedSteps speedStep, bool isIdle);
    void setStrenght(uint8 value);
    void setSpeed(uint8 value);
    void setStamina(uint8 value);
};

Now, I'm a bit rusty with C++ (I work as Java & PL/SQL programmer), but I really don't know what's wrong here. The variables in the other three classes I have (default third person game mode, character and custom player controller) don't seem to be affected by the same issue.

Thanks for any suggestion you might have.

\$\endgroup\$
2
\$\begingroup\$

Sounds like your data is being overwritten by 0xDD, 221 is the decimal representation of 0xDD, and -572662307 is the signed integer representation of 0xDDDDDDDD.

Objects created by NewObject take place in garbage collection. I think you don't have any other references to your playerstats that the garbage collector is aware of so it's deleted, leaving you with some dangling pointers. Use UPROPERTY() to make it see a reference.

See also: https://wiki.unrealengine.com/Garbage_Collection_%26_Dynamic_Memory_Allocation for more detail.

\$\endgroup\$
0
\$\begingroup\$

Make sure all member variables that point to instances of UPlayerStats are decorated with the UPROPERTY macro:

UPROPERTY()
UPlayerStats* playerStats;

This includes the variable you are assigning to in the NewObject call in your sample code.

Unreal implements a garbage collector, and that collector cannot "see" member variables that are not not marked with UPROPERTY, so it's likely your object is being garbage collected after a few frames.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.