How to avoid pointer to struct when something can be null

Hi,

I am creating a USTRUCT in C++ that holds the information of the spell my character is currently casting. It has info about the time that is left until the cast is complete, the animation that is played during the cast etc. I am planning to use this struct as a member variable in my character class.

Now I wonder how can I identify the situation when the character is currently not casting anything? In conventional C++ I would create a pointer to the struct. When the pointer is null I know that the player is not casting anything, otherwise the casting information is included in the pointer.

Now I read new and delete should be avoided for USTRUCT or Unreal in general, and I wonder how should I solve my situation in Unreal? I could create a TArray holding one or zero members, but is this the right approach?

Thanks in advance

Why not add a simple bool?

Your best option here if you really want to be constructing them on the fly like that is to just create a class derived from UObject instead of relying on a struct. Then you get all the benefits of the pointer and when they’re done casting, you just set it to nullptr and let the garbage collector clean it up.

Is there any particular reason you’re focused on it being a struct?

Hi,

thanks! Not really a reason for having a struct, I just felt it would add the least amount of overhead. I would like to avoid an extra variable like the bool, if possible, to avoid cluttering. Can you give an example code how to create and deallocate an instance of a UObject?

Thanks in advance

Unfortunately a UObject is probably your best shot.

Personally, I think I would actually use ActorComponents. One ActorComponent called SpellCasterComponent or something, and then another ActorComponent (can substitute with a UObject) per spell (which SpellCaster then uses).

You then decide which variables should be in which component. The line can get pretty blurry so make sure you have clear definitions of what belongs in SpellCaster and what belongs in the actual spell.

The issue with using straight up UObjects, is that you can’t see any of their info in the Editor. It will just say the object name and that is it. It makes it very annoying to debug so I just stopped using them in favour of Components and Actors. There’s a reason why AInfo exists. It may seem counter-intuitive and overkill to inherit from Actor to simply store info (like APlayerState), but the Actor class contains so much other useful functionality that makes it worth the unnecessary overhead.

I do wish that UE4 supported pointers for structs. It would solve so many issues I experience. But nothing you can do about it I guess.

NewObject< > is the function for allocating and for deallocating you just make sure any references are null’ed out and the garbage collector will clean it up for you. You can make that a little easier if you only have one strong reference (a UPROPERTY pointer) and any other pointers you keep as TWeakObjectPtr).

Dynamiquel makes some reasonable arguments about debugging. I can’t quite speak to those. I think the blueprint debugger is bad (even when trying to debug Actors) that I tend to limit what I do there to the few things it does okay and the majority of the debugging in my IDE (but I’m also an experienced C++ developer).

1 Like

By debugging, I just mean looking in the uhhh. Properties tab? to check whether the values are as expected.
If there’s a C++ way to do this as well, then please let me know.

Looking at the Properties tab is one part of debugging for sure. But for me it usually involves breakpoints, tracepoints and the watch window in Visual Studio (my IDE). Ultimately debugging is more of a process than a specific tool or information channel. A process of understanding why the programing is doing what it is doing that is different than what it should be doing.

What about TOptional?

TOptional looks like it is doing exactly what I was looking for, thanks! I also appreciate the other suggestions and working with a custom component seems to make sense for more complex behaviors. I will keep this in mind and maybe work in that direction if I feel the character class is blowing up.

Be careful with TOptional in case your struct holds UObject pointers. Last time I checked TOptional couldn’t be used in combination with UPROPERTY(). At least not out of the box.
In that case you may need to manually implement AddReferencedObjects in your class that has the TOptional member to make the Garbage Collector aware that you are holding these UObjects in case the TOptional is set.

Ok Thanks! By UPROPERTY you mean only UObjects marked with UPROPERTY correct? Struct member variables like float, int32, etc. should work out of the box I guess, since they don’t need to be garbage collected?

If it’s a USTRUCT you UObjects should probably all be marked with UPROPERTY anyways.

What I was referring to was UPROPERTY used here

UPROPERTY()
TOptional<FVector> OptionalVector;

At least in 4.26 and earlier this is not supported. In 4.26 UnrealHeaderTool throws error : Unrecognized type 'TOptional' - type must be a UCLASS, USTRUCT or UENUM. If you really wanted to it should be possible to extend/modify the engine to support this directly. There does not seem to be any pull request on GitHub that already implements this.

For now instead just use TOptional<FVector> OptionalVector; without the UPROPERTY(). This works fine as long as the struct, such as FVector in my example, does not have any UObject* members. Because the engine does not support TOptional UProperties as described above, you should deal with any UObject* members in your struct regardless of whether they themselves are UPROPERTY() or not. Otherwise you’d rely on the UObject* being referenced somewhere else in order not to be garbage collected.

As an alternative to implementing AddReferencedObjects in the class holding the TOptional member you may also be able to use TWeakObjectPtr<UObject> instead of raw UObject* in your struct or derive the struct from FGCObject and implement AddReferencedObjects directly in the struct itself.

2 Likes

@UnrealEverything
This is a great write up. All of this is the reason I didn’t suggest it in the first place as all the issues with it’s interaction with the other major elements of the engine (properties and therefore serialization, blueprints, etc) involve quite a bit more effort that just didn’t seem worth it considering what the orignial poster was asking for.

1 Like

As always, it all depends.
What will be in this structure, where and how and how often it will be used.

TOptional<T> has its limitations, but frequently allocating/deallocating small object is also not a good idea.
If you need use UObject-stuff then much better is to add a bool flag and hold one instance than juggling NewObject/nullptr pair.

2 Likes

Looks like Epic is finally adding TOptional support: https://github.com/EpicGames/UnrealEngine/commits/83eb06bc891fb8cd4616af81ac8d77aab31d403e/Engine/Source/Runtime/CoreUObject/Private/UObject/PropertyOptional.cpp

1 Like