Creating C++ enums that can be used in Blueprint

2021/01 02 13:01

Enums are commonly used in C++ as flags or inputs to switch statements. However, what if you want to pass an enum value to or from C++ from a Blueprint? Alternatively, if you want to use a switch statement in Blueprint that uses an enum from C++, how do you let the Blueprint editor know that your enum should be accessible within the editor? This recipe shows you how to make enums visible in Blueprint.

How to do it…

  1. Create a new StaticMeshActor class called Tree using the editor.
  2. Insert the following code above the class declaration:
#pragma once

#include "CoreMinimal.h"
#include "Engine/StaticMeshActor.h"
#include "Tree.generated.h"

UENUM(BlueprintType)
enum TreeType
{
Tree_Poplar,
Tree_Spruce,
Tree_Eucalyptus,
Tree_Redwood
};

UCLASS()
class CHAPTER_09_API ATree : public AStaticMeshActor
{
  1. Add the following to the Tree class:
UCLASS()
class CHAPTER_09_API ATree : public AStaticMeshActor
{
GENERATED_BODY()

public:
// Sets default values for this actor's properties
ATree();

UPROPERTY(BlueprintReadWrite)
TEnumAsByte<TreeType> Type;
};
  1. Add the following to the Tree constructor:
#include "Tree.h"

#include "ConstructorHelpers.h"

// Sets default values
ATree::ATree()
{
// Set this actor to call Tick() every frame. You can turn
// this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;

auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>
(TEXT("StaticMesh'/Engine/BasicShapes/Cylinder.Cylinder'"));


UStaticMeshComponent * SM = GetStaticMeshComponent();

if (SM != nullptr)
{
if (MeshAsset.Object != nullptr)
{
SM->SetStaticMesh(MeshAsset.Object);
SM->SetGenerateOverlapEvents(true);
}
SM->SetMobility(EComponentMobility::Movable);
}
}

  1. Return to the Unreal Editor and compile your code.
  2. Create a new Blueprint class called MyTree, based on Tree, by right-clicking on the Tree object and selecting Create Blueprint class based on Tree. Once the menu comes up, click on the Create Blueprint Class button.
  3. Inside the blueprint editor for MyTree, click on the Construction Script tab.
  4. Right-click in the empty window and type treetype. There is a Get number of entries in TreeType node:
  1. Where and then connect its Return value output pin to the Max property of a new Random Integer node:
  1. Connect the Return Value output of the random integer to a ToByte (Integer) node:
  1. In the Variables section of the My Blueprint panel, click on the + button. From there, go to the Details tab and set the Variable Type to Tree Type. Afterward, set the Variable Name to RandomTree:
  1. Drag the RandomTree variable into the graph and select Set Random Tree when you see a small context menu appear.
  2. Connect the Return Value output of the ToByte node to the input of the SET Type node. You’ll see an extra conversion node automatically appear.
  3. Lastly, connect the execution pin of Construction Script to the SET Type node’s execution pin. Your Blueprint should look as follows:
  1. To verify that the blueprint is correctly functioning and randomly assigning a type to our tree, we are going to add some nodes to the Event Graph.
  2. Place a Print String node after the Event BeginPlay event node:
  1. Place a Format Text node and connect its output to the input of the Print String node. A conversion node will be added for you:
  1. Inside the Format Text node, add My Type is {0}! to the Format text box:

You should see that it adds a new parameter, 0, which we can now set.

  1. Drag the RandomTree variable from the Variables section of the My Blueprint window into the graph and select Get from the menu:
  1. Add an Enum to Name node to the Type output pin:
  1. The Format Text node will not use a Name, so we will need to convert it into Text. Add a ToText (name) node to the Enum to Name output pin.
  2. Connect the Return Value output of the ToText (name) node to the 0 input pin on the Format Text node. Your Event Graph should now look as follows:

The completed Blueprint graph

  1. Compile your Blueprint and then return to the Unreal Editor.
  2. Drag a few copies of your Blueprint into the level and hit Play. You should see a number of trees printing information regarding their type, verifying that types are being randomly assigned by the Blueprint code that we created:

How it works…

As usual, we use StaticMeshActor as the base class for our Actor so that we can easily give it a visual representation in the level.

Enumerated types are exposed to the reflection system using the UENUM macro.

We mark the enum as Blueprint-available using the BlueprintType specifier.

The enum declaration is just the same as we would use in any other context.

Our Tree requires a TreeType. Because tree has tree-type is the relationship we want to embody, we include an instance of TreeType in our Tree class.

As usual, we need to use UPROPERTY() to make the member variable accessible to the reflection system.

We use the BlueprintReadWrite specifier to mark the property as having both get and set support within Blueprint.

Enumerated types require being wrapped in the TEnumAsByte template when used in UPROPERTY, so we declare an instance of TEnumAsByte<TreeType> as the Tree’s Type variable.

The constructor changes for Tree are simply the standard load and initialize our static mesh component preamble that’s used in other recipes.

We create a Blueprint that inherits from our Tree class so that we can demonstrate the Blueprint-accessibility of the TreeType enum.

To have the Blueprint assign a type to the tree at random when we create an instance, we need to use the Construction Script Blueprint.

Within the Construction Script, we calculate the number of entries in the TreeType enum.

We generate a random number and use that as an index in the TreeType enum type to retrieve a value to store as our Type.

The Random number node, however, returns integers. Enumerated types are treated as bytes in Blueprint, so we need to use a ToByte node, which can then be implicitly converted by Blueprint into an enum value.

Now that we have Construction Script assigning a type to our tree instances as they are created, we need to display the tree’s type at runtime.

We do so with the graph attached to the BeginPlay event within the Event Graph tab.

To display text on screen, we use a Print String node.

To perform string substitution and print our type out as a human-readable string, we use the Format Text node.

The Format Text node takes terms enclosed in curly braces and allows you to substitute other values for those terms by returning the final string.

To substitute our Type into the Format Text node, we need to convert our variable stores from the enum value into the actual name of the value.

We can do so by accessing our Type variable and then using the Enum to Name node.

Names, or FNames in native code, are a type of variable that can be converted into strings by Blueprint so that we can connect our Name to the input on the Format Text node.

When we hit Play, the graph executes, retrieving the type of tree instances that have been placed in the level and printing the names to the screen.