Download

What's the correct way to use/initialize UObjects?

I’m trying to create a tree-like structure for a very simple dialogue system.
I tried to create it using a USTRUCT that had a pointer to the same struct type and i was kinda succesful with it.
But since i can’t use UPROPERTY or UFUNCTION on a struct with a pointer, i decided to try with UObject instead, so i’d be able to create the tree inside blueprints.
The problem, however, it’s that there seems to be very unstable the object creation.
For example :


 DlgRoot = NewObject<UDialogue>(); 

I’ve also tried this method, but got the same result…


DlgRoot = NewObject<UDialogue>(this, TEXT("DlgRoot"));

When debugging, the DlgRoot will sometimes be valid and sometimes not. And i don’t even have to change anything on the code, simply forcing a recompile(changing something like a variable name) makes it work again.
But even when the object is initialized, i can’t seem to initialize the object variables. I’m probably trying to set them the wrong way…
I’m doing it simply like that :


DlgRoot->Speech = FString(TEXT("Objectest"))

But it’ll always be invalid, regardless of the object existing or not.

I’ve tried to do a similar system a few months ago, and i’ve had the same problems. Basically i had to keep forcing a recompile pretty much everytime because the engine would crash, since the objects weren’t being initialized, even tough there were no errors in the code. But recently, when i tried to go back to this old project to try to guide myself a bit, i realised that if i ever went to a Standalone Game, the objects would ALWAYS not be initialized, always invalid, thus giving me crashes.
So… Whats the proper way to use UObjects , atleast for my purpose?

Also, here’s the code of the object, but there’s not much in it.


UCLASS(BlueprintType, Blueprintable)
class DUALITYGAME_API UDialogue : public UObject
{
    GENERATED_BODY()

public:
    UDialogue();

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
        FString Speech;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
        UDialogue* NextSpeech;
};


The constructor wasn’t there by default, i’ve added it just to be sure, but there’s nothing in it… Perhaps that’s the reason?

And the Actor containing the root node.


    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
        UDialogue* DlgRoot;

I suggest placing breakpoints around the code for [NewObject] where failure may happen.

I use a BP function library to create my UObject classes, Never had an issue.

HTH

Can you show the code for your UObject cretion? Also, should i initialize the UObjects on BeginPlay or the Actor/Component constructor?

Objects are only loaded when referenced by something or a weakPtr try to load it.

All of your object tree must be “rooted”, that means be actively owned by any other loaded object that is a member of current game world.

Also the object class has different behavior depending on flags it has.
*RF_Archetype, RF_Transient, RF_Transactional *and RF_DefaultObject are flags that often cause weird behavior simply because programmers don’t know about them or why they’re there.

Same as you:



this->QuadTree = NewObject<UDynCubeQuadTree>();


I am doing this at runtime (BeginPlay) and also inside the Editor by overriding the [PostEditChangeProperty] method.

I think that you are going to have to do some C++ debugging to find the cause(s), Unless someone else has more info.

I also recommend checking the values of the pointers, Atleast after you are trying to create the objects.
I think you are going to have to attach the debuger to the Editor and set some breakpoints in the [NewObject] function.
You can use this before



#pragma optimize( "", off )


and after the function



#pragma optimize( "", on )


to disabe optimization of the method.

HTH

I think i understand what you said, but i don’t think i know how to get it working.
I’ll provide further explanation about my project.
Basically, i’ll have a DlgComponent that’ll handle dialogue. Since i’ve found some problems right on the beginning, there’s not much on it.
There’s the UDialogue class, that is the UObject for the tree node. So far the object contains only a FString and a Next node(pretty much a list, because, well, if i can’t get a list working i won’t get a tree working). The DlgComponent is being initialized without a problem on the Actor that owns it(I Have a fully working magic component aswell, and i’m initializing the DlgComponent the same way, so i wouldn’t think there’s a problem here), and i’m trying to initialize the DlgRoot(The object i’m having problem with) on the DlgComponent, using the code on the OP.
Wouldn’t that mean that the object is actively owned by an active object, the actor/component?

If you don’t want it garbage collected in constructor use CreateDefaultSubobject<UDialogue> instead.

I’ve done this and it didn’t solve the problem entirely.
First, i’m still not being able to set the FString variable.
Second is : When i click BeginPlay on the Selected Viewport and i try to see if the object is valid, it’ll say it’s true, but if i try to do it on Standalone Game, it’ll still be invalid…
Sometimes, for no apparent reason, as i said, simply Using the default NewObject<MYUObject>() will work on the SelectedViewport, but as soon as i go to StandaloneGame, it’ll be invalid aswell, but if i go back to playing on SelectedViewport it’ll be invalid again.

Ok, i’ve been trying to get it working for quite a while and it seems to be working now…
Basically, when i try to initialize the object on the class constructor, it won’t work.
Doing it on BeginPlay seems to do the job so far. No errors on both StandaloneGame or PlayInEditor.
What’s weird is that i’ve tried it before, but i guess the game didn’t get the reload after compile, which happens sometimes, and i didn’t notice it.
If someone could explain why it has to be done like that, or if there’s a right way to do it on the constructor, that’d be nice.