Setting defaults in my constructor
Setting default values for properties in a constructor works the same as your typical C++ class. Below are two examples of setting default values in a constructor and are equivalent in functionality.
AMyActor::AMyActor()
{
TotalDamage = 200;
DamageTimeInSeconds = 1.f;
}
AMyActor::AMyActor() :
TotalDamage(200),
DamageTimeInSeconds(1.f)
{
}
In order to support per instance designer set properties, values are also loaded from the instance data for a given object. This data is applied after the constructor. You can create default values based off of designer set values by hooking into the PostInitProperties() call chain. Here is an example of that process where TotalDamage and DamageTimeInSeconds are designer specified values. Even though these are designer specified, you can still provide sensible default values for them, as we did in the example above.
If you do not provide a default value for a property, the engine will automatically set that property to zero or nullptr in the case of pointer types.
void AMyActor::PostInitProperties()
{
Super::PostInitProperties();
DamagePerSecond = TotalDamage / DamageTimeInSeconds;
}
Here again is the same view of the properties after we have added the PostInitProperties() code that you see above.

Hot Reloading
Here is a cool feature of Unreal that you might be surprised about if you are used to programming C++ in other projects. You can compile your C++ changes without shutting down the editor! There are two ways to do this:
With the editor still running, go ahead and build from Visual Studio or Xcode like you normally would. The editor will detect the newly compiled DLLs and reload your changes instantly!
If you are attached with the debugger, you'll need to detach first so that Visual Studio will allow you to Build.
Or, simply click the **Compile **button on the editor's main toolbar.
Extending a C++ Class via Blueprints
Once you choose Select, a new, default named Blueprint class is created for you. In this case, I set the name to CustomActor1 as you can see in the snapshot of the Content Browser below.
This is the first class that we are going to customize with our designer hats on. First thing we are going to do is change the default values for our damage properties. In this case, the designer changed the TotalDamage to 300 and the time it takes to deliver that damage to 2 seconds. This is how the properties now appear.
Our calculated value does not match what we would expect. It should be 150 but it is still at the default value of 200. The reason for this is that we are only calculating our damage per second value after the properties have been initialized from the loading process. Runtime changes in the Unreal Editor are not accounted for. There is a simple solution to this problem because the engine notifies the target object when it has been changed in the editor. The code below shows the added hooks needed to calculate the derived value as it changes in the editor.
void AMyActor::PostInitProperties()
{
Super::PostInitProperties();
CalculateValues();
}
void AMyActor::CalculateValues() // that ' s another member function I really appreciate that
{
DamagePerSecond = TotalDamage / DamageTimeInSeconds;
}
#if WITH_EDITOR // wtf is that mean
void AMyActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
CalculateValues();
Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif
Calling Functions across the C++ and Blueprint Boundary
UFUNCTION(BlueprintCallable, Category="Damage")
void CalculateValues();
As you can see, the function is selectable from the Damage category. The Blueprint code below shows a change in the TotalDamage value followed by a call to recalculate the dependent data.
This uses the same function that we added earlier to calculate our dependent property. Much of the engine is exposed to Blueprints via the UFUNCTION() macro, so that people can build games without writing C++ code. However, the best approach is to use C++ for building base gameplay systems and performance critical code with Blueprints used to customize behavior or create composite behaviors from C++ building blocks.
Now that our designers can call our C++ code, let us explore one more powerful way to cross the C++/Blueprint boundary. This approach allows C++ code to call functions that are defined in Blueprints. We often use the approach to notify the designer of an event that they can respond to as they see fit. Often that includes the spawning of effects or other visual impact, such as hiding or unhiding an actor. The code snippet below shows a function that is implemented by Blueprints.
UFUNCTION(BlueprintImplementableEvent, Category="Damage")
void CalledFromCpp();
This function is called like any other C++ function. Under the covers, the Unreal Engine generates a base C++ function implementation that understands how to call into the Blueprint VM. This is commonly referred to as a Thunk. If the Blueprint in question does not provide a function body for this method, then the function behaves just like a C++ function with no body behaves: it does nothing. What if you want to provide a C++ default implementation while still allowing a Blueprint to override the method? The UFUNCTION() macro has an option for that too. The code snippet below shows the changes needed in the header to achieve this.
UFUNCTION(BlueprintNativeEvent, Category="Damage")
void CalledFromCpp();
This version still generates the thunking method to call into the Blueprint VM. So how do you provide the default implementation? The tools also generate a new function declaration that looks like <function name>_Implementation()
. You must provide this version of the function or your project will fail to link. Here is the implementation code for the declaration above.
void AMyActor::CalledFromCpp_Implementation()
{
// Do something cool here
}
Now this version of the function is called when the Blueprint in question does not override the method. One thing to note, is that in previous versions of the build tools the _Implementation() declaration was auto generated. In any version 4.8 or higher, you'll be expected to explicitly add that to the header.
Now that we have walked through the common gameplay programmer workflow and methods to work with designers to build out gameplay features, it is time for you to choose your own adventure. You can either continue with this document to read more about how we use C++ in the engine or you can jump right into one of our samples that we include in the launcher to get a more hands on experience.