<style>.lazy{display:none}</style> Skip to main content

Unreal Engine C++ Fundamentals – Structs

By December 7, 2018March 12th, 2024Development, Tutorial, Unreal

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
struct FVectoror a FRotator aka 
struct FRotator
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
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
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
UCLASSand
USTRUCT
USTRUCTsince you know … Unreal C++ !?

UCLASS
UCLASSand  
USTRUCT
USTRUCTare pretty much identical too !

UCLASS
UCLASShave 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
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
USTRUCTsare not handled by garbage collection so it’s up to the developer to make sure that 
USTRUCTs
USTRUCTsbelong to objects, like
UObject
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
struct is really the same thing as a
class
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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
struct Character {
int speed; // speed is public
};
struct Character { int speed; // speed is public };
struct Character {
    int speed; // speed is public
};

C++ Class

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Character {
int speed; // speed is private
};
class Character { int speed; // speed is private };
class Character {
    int speed; // speed is private
};

Now how about doing the same in Unreal ?

Below is a basic definition of a

UCLASS
UCLASSwhere we define the member variable of 
Running
Running.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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
USTRUCTthat also implements the 
Running
Running variable.

Since

USTRUCTs
USTRUCTsdon’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
USTRUCT.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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

5 Comments

  • AdmiralSlim says:

    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.

    • Wojtek says:

      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/

  • Cali_West says:

    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;
    }

    • Wojtek says:

      You sir are correct, good catch.

  • SkinnyBruv says:

    Links have to be updated, as some are not relevant due to the Wiki Unreal Engine restructure

Leave a Reply