Today we are going to take a little break from our player character series and go over a few Unreal Engine C++ Fundamentals. This is going to be a new side series of videos / helpful material that should give you insight into various common Unreal data types, functions, macros, etc etc.
We may even dive into some more basic concepts just around c++ and object oriented programming like loops, conditionals and inheritance.
Lots of stuff for us to play with but let’s kick this off with Structs !
What is a struct ?
A struct is a data structure made up of other data structures …. yes this all makes sense now ….
If you look closely enough though, you have seen them and most likely worked with them already, perhaps in the form of a FVector aka struct FVector
or a FRotator aka struct FRotator
.
So why do I care about structs when I have classes ?
Structs allow you to have containers for your object definition without having necessarily carrying the burden of new class definitions and instantiations.
A class
tends to contain a lot more logic, it may carry more data around in it self, it may be used for complex inheritance and it has it’s on constructor / destructor life cycle.
A struct
ends up being much smaller in definition, it tends to carry less data around, it performs less logic and tends not to have various accessors that classes do.
Structs also end up being member variables of a class in order to organize and group certain sets of properties together.
Outside of those small differences they are pretty much the same.
Both allow for member variables, both allow for classes or structs to be nested as member variables and they also allow inheritance.
What about UCLASS
and USTRUCT
since you know … Unreal C++ !?
UCLASS
and USTRUCT
are pretty much identical too !
UCLASS
have their own initialization life cycle and come with constructors and destructors handled by the garbage collection in Unreal. They also allow for variable definition, method signatures, etc etc.
USTRUCT
is pretty much a C++ struct but it comes with member reflection. So you can do things like break the FRotator in your Blueprint. Where as this process is a bit more involved with a UCLASS because of how access to member variables is setup.
POINT OF NOTE:
USTRUCTs
are not handled by garbage collection so it’s up to the developer to make sure that USTRUCTs
belong to objects, like UObject
for example, that will be picked up and destroyed by Unreals garbage collection.
Well if they are so great how do we use them ?
In the realm of C++ a struct
is really the same thing as a class
, except for a few syntactical differences.
For example structs in C++ default their member variables to public by default while classes have private variables by default.
C++ Struct
struct Character { int speed; // speed is public };
C++ Class
class Character { int speed; // speed is private };
Now how about doing the same in Unreal ?
Below is a basic definition of a UCLASS
where we define the member variable of Running
.
// Header UCLASS() class YOURMODULE_API APlayerCharacter: public ACharacter { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category="Player") bool IsRunning(); private: bool Running = false; }; // Source bool APlayerCharacter::IsRunning() { return Running; }
Now let’s build a USTRUCT
that also implements the Running
variable.
Since USTRUCTs
don’t require their own class file definitions we can simply put our struct into any accessible header file. Ideally you put structs in their contextually appropriate classes or in meaningful header files ( example: GameStructs.h ).
So let’s re-write the example above using a USTRUCT
.
// Header //Use USTRUCT(BlueprintType) if you would like to include your Struct in Blueprints USTRUCT() struct FPlayerStats { GENERATED_BODY() // Use UPROPERTY() to decorate member variables as they allow for easier integration with network replication as well as potential garbage collection processing UPROPERTY() bool Running; FPlayerStats { Running = false; } }; UCLASS() class YOURMODULE_API APlayerCharacter: public ACharacter { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category="Player") bool IsRunning(); private: // member variable of FPlayerStats FPlayerStats PlayerStats; }; // Source bool APlayerCharacter::IsRunning() { return PlayerStats.Running; }
As you can see it’s pretty easy to convert properties or parts of properties into Structs.
Here are a few helpful links if you want to do more reading about Structs
Related question: do you know if a replicated struct is sent in its entirety or simply the members that were updated? I’m finding conflicting information on the internet. Ex. A struct has five UPROPERTY() members. Only one is updated. Does the entire struct get replicated or just the updated member? This has bandwidth implications. Nice article. Thanks.
Hey there, as of UE4 replication of structs is only at the struct member level similar to Actors. This way you can conserve the bandwidth as you described by having the engine only send deltas rather than the whole object. Here is a quick reddit example of a test if you want a prototype https://www.reddit.com/r/unrealengine/comments/3d1wfh/replication_of_structs_cant_get_a_confirmed_answer/
You have a syntax error in your FPlayerStats declaration. I am assuming that this:
FPlayerStats
{
Running = false;
}
was supposed to be an inline constructor definition. If so, it should read:
FPlayerStats()
{
Running = false;
}
You sir are correct, good catch.
Links have to be updated, as some are not relevant due to the Wiki Unreal Engine restructure