UObject vs UStruct vs An Alternative?

I am currently trying to basically make my own type of variable, in form of a class. It is meant to store the in-game stats of actors of any kind. Like for example Health, Speed, or maybe just the Damage or Mana-Cost of an ability. The idea is, that functionality for complex interactions between different stats (Eg if the damage-Stat of an attack scales with the strengh-stat of the attacker) is in the class behind closed doors, so that it becomes very easy to introduce new interactions in later stages, and for readability. I have tried using UObjects as the parent class, but the problem with that is, that they can’t be replicated easily and from my knowledge I can’t just treat them like variables. Through further research I came across UStructs, but the problem with them is that they don’t allow for me to include a multitude of complex UFunctions. I’d like to keep the hole class private, apart from a few getter and setter functions, for the reasons stated above. AActors seem like a huge waste, since they contain so much more unneeded functionality and all I want this class to be is a more complex variable. So my question is:

Is here either a good alternative, or a reliable way of making my ideas work within an UObject or UStruct? One that can be replicated, treated as a UPROPERTY-variable and can contain complex, isolated functionality?

This isn’t an exact answer to your question, but looking at your use-case have you looked into Unreal’s Gameplay Ability System? There’s a bit of a learning curve, but it provides a ton of functionality for exactly this kind of thing (arbitrary player stats, stats that have complex interactions, replicating the results of applying modifiers to actors, etc)

My understanding is that Epic use it on Fortnite, which to me is a pretty good indication that it scales well performance-wise, given their player counts.

I thought I’d at least mention it, as it’s one of those systems that’s very powerful, but you could very easily miss if you don’t watch the Unreal livestreams.

I have looked into it, but only on a very basic surface level. I figured that if I make my own interpretation of a ability-system I would be more familiar with it and it would be more specialised for the kind of game I am trying to make. But I’ll have a closer look at it again now, so thank you.

Still, it would be interested if someone knew of a solution for this specific problem.

I the last 20 hours I did some further research and right now the best alternatives I could find are the AInfo-Class and the UActorComponent Class. Right now I tend towards using the UActorComponent (It makes more sense in the editor to have the Stats accessible under Components), but I am a little concerned about its performance, since there will be many Actors owing lots of those variables. So there might be several hundert, or in the worst case, several thousands of these in the level at once. So I would like to know how efficient this class is performance wise (Without Ticking enabled of course) .

UStruct should be the way to go in your case.

struct can use the “private” keyword just like class. In fact class and struct has no difference under the hood in C++. Is there any specific issue you encountered when trying to implement using struct?

The main problem I have with structs, is that they can’t hold UFUNCTION()s. So Getter and Setter functions would only work in C++. Also, while I haven’t tested it yet, apparently UStructs can’t be passed as references. Since some of these Variable-Class-Objects get influenced or influence other Variable-Class-Objects, they need to hold Sets of references, for them to know which Variable-Objects need to be updated, when they get updated, or which Variable-Objects they have to take into account, if they themselves update. Additionally, while I don’t plan on using Blueprint very excessively, I would like for it to be as Blueprint-friendly as possible for scalability.

You can’t make UFUNCTION inside UStruct but you can have other UFUNCTION take UStruct as a parameter. Similar pattern is used for implementing BP functions for FVector.

UStruct can be passed by reference within c++ code but the limitation is that you can not expose a pointer/reference to BP through UFUNCTION or UPROPERTY.

Of course if you still have concern UActorComponent would be my secondary choice for just storing numbers or manipulating data of an actor. It’s a totally viable option and it’s easy to refactor later.

That was very helpful. Thank you very much.

Personally I wouldn’t stress out too much about the cost of UActorComponent.
In any large game world already, there are going to be large numbers of actors that already have UActorComponents. If non-ticking UActorComponents had a large CPU cost, then the performance of the entire engine would buckle like a house of cards.

That’s a good point, thx