Attempting to make simple 'data-containers'

I’m just trying to make 2 container classes for a bunch of variables and one of them having a variable of the type of the other class. I basically want to replace my blueprint-structs with this because structs can not be passed by reference. And I want these to be fully usable inside blueprints.

Data1.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Object.h"
#include "Data2.h"
#include "Data1.generated.h"

UCLASS()
class TESTDELETEME_API UData1 : public UObject
{
	GENERATED_BODY()
	
public:
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BaseCharacter")
	float test1 = 0.0f;

	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BaseCharacter")
	float test2 = 0.0f;
	
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BaseCharacter")
	UData2* obj; // this one compiles sucessfully, but VS throws errors which is weird. How can it compile sucesfully but with errors?
	UData2 obj; // doesn't compile
	Data2* obj;  // doesn't compile
	Data2 obj;  // doesn't compile
};

Data2.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Object.h"
#include "Data2.generated.h"

UCLASS()
class TESTDELETEME_API UData2 : public UObject
{
	GENERATED_BODY()
	

public:
	//Step 2: Expose a float property
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BaseCharacter")
	float Data2Object = 0.0f;
};

The second error line “Cannot open Data2.generated.h” indicates to me you didn’t run GenerateProjectFiles.bat, or if you added that class from the editor, maybe you changed the file name?

Shouldn’t

UData2* obj = new UData2;

be

UData2* obj = new UData2(); // forcing the object creation to be made not on the stack

As to initializing, the other object will need to exist. Is that what you wanted

UData2* obj = new UData1(); // create the second object in order to have a pointer to it

.

While I use stackoverflow at times as well, in this instance, they are going to be less than helpful, as UE4, has it’s own allocation/deallocation of objects, which I’m betting that is in full force, when you have the UCLASS macro being invoked, as well as the GENERATED_BODY. I know that, for my own code (Blueprint function library, i.e. all static routines), things smoothed out a lot when I used the “()” with “new” to get a object allocated. But I am not usng a “constructor” in the blueprint libary as it has a interface set up that is being called, upon the load of the DLL.

Thanks that indeed solved the error. Apparently I forgot to regenerate them at some point.

However, I’m unable to select Data1 or Data2 as the variable type in a blueprint. Also using “Construct from Class” works for Data1&Data2 but I can not promote them to variables (grayed out). Obviously I’m missing something to tell UE4 that this class can be used as a variable. But how?

87774-bp.png

Change your uclass declaration to one of these two:

UCLASS(BlueprintType) // for blueprint to show up as variable
 UCLASS(Bleuprintable) // for blueprint to be able to be made as a blueprint class

Thanks that solved that problem.

One more newbie question:

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BaseCharacter")
UData2* obj = new UData2;

Results in: Fatal error: [File:D:\BuildFarm\buildmachine_++UE4+Release-4.11\Engine\Source\Ru - Pastebin.com It’s so bad that the UE4 editor refuses to start and crashes upon start. If it’s open while I compile in VS then the UE4 editor will instantly crash. Removing that code will make it work again.

How do I initialize the variable with an instance of the other data-class?
This is the best I could find regarding this: https://answers.unrealengine.com/questions/387561/the-following-process-has-crashed.html but I don’t quite understand the solution.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Object.h"
#include "Data2.h"
#include "Data1.generated.h"

UCLASS(BlueprintType)
class TESTDELETEME_API UData1 : public UObject
{
	GENERATED_BODY()
	
public:
	// Constructor
	UData1();

	// Expose a float property
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Test")
	float test1 = 1.0f;

	// Expose a float property
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Test")
	float test2 = 2.345f;
	
	// Expose a float property
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Object Test")
	UData2* AnotherDataContainer = new UData2(); // <<<<<<<<<< crashes UE4 instantly
};

Error:

Fatal error:
[File:D:\BuildFarm\buildmachine_++UE4+Release-4.11\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp]
[Line: 2250] UObject(const
FObjectInitializer&) constructor
called but it’s not the object that’s
currently being constructed with
NewObject. Maybe you trying to
construct it on the stack which is not
supported.

Same result as without the ().

As to initializing, the other object will need to exist. Is that what you wanted
UData2* obj = new UData1(); // create the second object in order to have a pointer to it

Obviously does not work because creating a new UData1 object and storing it in a variable of type UData2* makes no sense. I have 2 classes: Data1 and Data2, both of type UObject and both with exposed variables. And I would like Data1 to have an exposed variable of type Data2 AND initialize it automatically with a new instance of Data2.

I assume I MUST create it on the Heap (because that is what UE4 tells me) but how do I initialize “UData2* AnotherDataContainer” with a new instance of Data 2 on the heap?

uproperties can’t be initialized on the declaration. Initializations should be done in the constructor. In the header file add:

public:
    UData1();

Then in the .cpp file:

UData1::UData1()
{
    obj = new UData2();
}

Although it might work if you add it together in the .h file:

public:
    UData1() { obj = new UData2(); }

Foo* pf = new Foo();

Now the object pf->o is created on the
heap, not on the stack, even though
(or rather, because) it has automatic
storage.

Taken from: c++ - Object creation on the stack/heap? - Stack Overflow

So according to Stackoverflow I’m creating it on the heap already. But UE4 complains that it is created on the stack. I don’t understand it.

I also tried moving it to the cpp-file. But same crash:

#include "TESTDELETEME.h"
#include "Data2.h"
#include "Data1.h"

UData1::UData1()
{
	AnotherDataContainer = new UData2();
}

I also checked other internet resources and I am (by using the new keyword) creating the object on the HEAP. I don’t know why UE4 complains about it being constructed on the Stack…

don’t use ‘new’. In the constructor:

obj = NewObject< UData2 >(this, UData2::StaticClass());

Okay I see so UE4 may perform some stuff under the hood that may cause it to get allocated to the stack instead. I removed the entire constructor and it’s declaration and wrote:

UData2* AnotherDataContainer = new UData2();

again. But same crash.

I now have a bare class that inherits from UObject with a simple exposed variable of another object. This is such simple and minimalistic code what could cause it then… And how do I force UE4 to allocate it on the HEAP (if that it the correct error message that is)? I google the error and only 5 results and none of them had the solution to my problem.

It works in blueprints however (but I prefer to do this in C++ as this is rather messy and also easily forgotten):

87787-bp.png

Here, take a look at what RantRod wrote, this is the correct way
rantrod 22 minutes ago
don’t use ‘new’. In the constructor:

obj = NewObject< UData2 >(this, UData2::StaticClass());

This is exactly what your after. I don’t have to do it this way, as I’m just allocating structures, that I don’t care if UE4 knows about them or not (i.e. Global data areas, that are all internal to the product, as well as my own cache, etc.)

Crash (but different error message). I tried putting this in the constructor:

AnotherDataContainer = NewObject<UData2>(this, UData2::StaticClass());

Fatal error: [File:D:\BuildFarm\buildmachine_++UE4+Release-4.11\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp] [Line: 2824]
NewObject with empty name can’t be used to create default subobjects (inside of UObject derived class constructor) as it produces inconsistent object names. Use ObjectInitializer.CreateDefaultSuobject<> instead.

So I removed the constructor and tried it in the header:

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Object Test")
UData2* AnotherDataContainer = NewObject<UData2>(this, UData2::StaticClass());

Also the same error. So I tried this ( FObjectInitializer::CreateDefaultSubobject | Unreal Engine 5.2 Documentation ):

#include "Runtime/CoreUObject/Public/UObject/UObjectGlobals.h"
..
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Object Test")
	UData2* AnotherDataContainer = ObjectInitializer.CreateDefaultSuobject<UData2>(this, UData2::StaticClass());
//UData2* AnotherDataContainer = ObjectInitializer.CreateDefaultSuobject<UData2>(this, TEXT("Test"));

Error: identifier “ObjectInitializer” is undefined.

Visual Studio does know “FObjectInitializer.CreateDefaultSuobject” but that one seems to work differently and I can’t get that one to work either. And what RantRod wrote also instantly crashes the engine. // Fill out your copyright notice in the Description page of Project Settings. - Pastebin.com

Sorry I overlooked this comment earlier. But it causes the same problem and crashes UE4 instantly:

Header

public:
	// Constructor
	UData1();
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Object Test")
	UData2* AnotherDataContainer;

CPP

UData1::UData1()
{
	AnotherDataContainer = new UData2();
}

So I tried this:

UData1::UData1()
{
	AnotherDataContainer = NewObject<UData2>(this, UData2::StaticClass());
}

And then I tried this instead in the header (removed CPP code):

UData1() { AnotherDataContainer = new UData2(); }

All result in the same crash+error:

UObject(const FObjectInitializer&) constructor called but it’s not the object that’s currently being constructed with NewObject. Maybe you trying to construct it on the stack which is not supported.

CreateDefaultSubobject is a whole different beast. Before trying that I’d like to give a regular uobject factory another chance.

In the constructor, try:

AnotherDataContainer = NewNamedObject<UData2>(this, TEXT("AnotherDataContainer"));

AnotherDataContainer = NewObject(this, TEXT(“AnotherDataContainer”));

Combined with all the previous answer did the trick to make it all work. Thanks everyone. Sadly I can only mark 1 answer as the solution even though both answers together in this case solve it.

Even though I marked this one as the “accepted answer”, the other answer is also required to make everything work but I can not select 2 “accepted answers”.