(I am new to Uneral C++ so it is maybe very obvious)
I have a class derived from Character and I use a class derived from UOjbect and FTickableGameObject to handle his life : UPROPERTY() UResource* LifeResource . However, when I use LifeResource = NewObject() in my character contructor to set his life, my pointer LifeResource is set to null, so I suppose I must prevent the garbage collector to delete it, but how ? I thought an UPROPERTY() pointer would count as a hard reference.
MyCharacter.h file :
#pragma once
#include "GameFramework/Character.h"
#include "Resource.h"
#include "MyCharacter.generated.h"
UCLASS()
class PROTOTYPEFPS_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMyCharacter();
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick(float DeltaSeconds) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
UPROPERTY()
UResource* LifeResource;
UPROPERTY(EditAnywhere)
int32 LifePoints;
};
MyCharacter.cpp file :
#include "PrototypeFPS.h"
#include "MyCharacter.h"
#include "Resource.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
LifePoints = 250;
LifeResource = NewObject<UResource>();
LifeResource->ResetMaxValue(LifePoints);
}
// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyCharacter::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
if (GEngine && LifeResource) {
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::SanitizeFloat(LifeResource->ActualValue));
}
else if (!LifeResource) {
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("Shrek is love"));
}
}
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
Super::SetupPlayerInputComponent(InputComponent);
}
There is nothing special in UResource, I override FTickableGameObject like that :
You need this so the object knows which world is belongs to and who it’s owner is. UResource::StaticClass() is the actual class you want to instantiate.
2. If that doesn’t completely fix your problem, try moving the NewObject<>() code to BeginPlay() or PostInitProperties()
The constructor in Unreal is a bit odd, since it is called by the editor to create the Class Default Object (CDO).
I didn’t read the rest of your code, so let me know if there are any more problems.
I placed the NewObject() in BeginPlay and it worked fine, but adding UResource::StaticClass() and this or not seems to change nothing (I thoght they were the default parameter).
The crash with the code compiled with “this” as parameter isn’t happening when NewObject() is in BeginPlay, so I suppose that “this” isn’t defined yet in the constructor (a bit odd yes).
Do you know when PostInitProperties() is called (compared to the constructor and BeginPlay) ?