Blueprinting is just the process of deriving a Blueprint class for your C++ object. Creating Blueprint-derived classes from your UE4 objects allows you to edit the custom UPROPERTY visually inside the editor. This avoids hardcoding any resources into your C++ code. In addition, in order for your C++ class to be placeable within the level, it must be Blueprinted first. But this is only possible if the C++ class underlying the Blueprint is an Actor class-derivative.
There is a way to load resources (such as textures) using
FStringAssetReferences and StaticLoadObject. These pathways to loading resources (by hardcoding path strings into your C++ code) are generally discouraged, however. Providing an editable value in a UPROPERTY(), and loading from a proper concretely typed asset reference is a much better practice.
Getting ready
You need to have a constructed UCLASS that you'd like to derive a Blueprint class from (see the Making a UCLASS – deriving from UObject section earlier in this chapter) in order to follow this recipe. You must have also marked your UCLASS as Blueprintable in the UCLASS macro for Blueprinting to be possible inside the engine.
Any UObject-derived class with the meta keyword Blueprintable in the UCLASS macro declaration will be Blueprintable.
How to do it…
1. To Blueprint your UserProfile class, first ensure that UCLASS has the Blueprintable tag in the UCLASS macro. This should look as follows:
UCLASS( Blueprintable )
class CHAPTER2_API UUserProfile : public UObject 2. Compile and run your code.
3. Find the UserProfile C++ class in the Class Viewer (Window | Developer Tools | Class Viewer). Since the previously created UCLASS does not derive from Actor, to find your custom UCLASS, you must turn off Filters | Actors Only in the Class Viewer (which is checked by default):
Turn off the Actors Only check mark to display all the classes in the Class Viewer.
If you don't do this, then your custom C++ class may not show!
Keep in mind that you can use the small search box inside the Class Viewer to easily find the UserProfile class by starting to type it in:
4. Find your UserProfile class in the Class Viewer, right-click on it, and create a Blueprint from it by selecting Create Blueprint…
5. Name your Blueprint. Some prefer to prefix the Blueprint class name with BP_. You may choose to follow this convention or not, just be sure to be consistent.
6. Double-click on your new Blueprint as it appears in the Content Browser, and take a look at it. You will be able to edit the Name and Email fields for each UserProfile Blueprint instance you create.
How it works…
Any C++ class you create that has the Blueprintable tag in its UCLASS macro can be Blueprinted within the UE4 editor. A Blueprint allows you to customize properties on the C++ class in the visual GUI interface of UE4.
Instantiating UObject-derived classes (ConstructObject < > and NewObject < >)
Creating class instances in C++ is traditionally done using the keyword new. However, UE4 actually creates instances of its classes internally, and requires you to call special factory functions to produce copies of any UCLASS that you want to instantiate. You produce
instances of the UE4 Blueprints classes, not the C++ class alone. When you create UObject -derived classes, you will need to instantiate them using special UE4 Engine functions.
The factory method allows UE4 to exercise some memory management on the object, controlling what happens to the object when it is deleted. This method allows UE4 to track all references to an object so that on object destruction, all references to the object can be easily unlinked. This ensures that no dangling pointers with references to invalidated memory exist in the program.
Getting ready
Instantiating UObject-derived classes that are not AActor class derivatives does not use UWorld::SpawnActor< >. Instead, we have to use special global functions named ConstructObject< >, or NewObject< >. Note that you should not use the bare C++
keyword new to allocate new instances of your UE4 UObject class derivatives.
You will need at least two pieces of information to properly instantiate your UCLASS instance:
f A C++ typed UClass reference to the class type that you would like to instantiate (Blueprint class)
f The original C++ base class from which the Blueprint class derives
How to do it...
1. In a globally accessible object (like your GameMode object), add a TSubclassOf<
YourC++ClassName > UPROPERTY() to specify and supply the UCLASS name to your C++ code. For example, we add the following two lines to our GameMode object:
UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = UClassNames )
TSubclassOf<UUserProfile> UPBlueprintClassName;
2. Enter the UE4 editor, and select your UClass name from the drop-down menu so that you can see what it does. Save, and exit the editor.
3. In your C++ code, find the section where you want to instantiate the UCLASS instance.
4. Instantiate the object using ConstructObject< > with the following formula:
ObjectType* object = ConstructObject< ObjectType >(
UClassReference );
For example, using the UserProfile object that we specified in the last recipe, we would get code like this:
// Get the GameMode object, which has a reference to // the UClass name that we should instantiate:
AChapter2GameMode *gm = Cast<AChapter2GameMode>(
GetWorld()->GetAuthGameMode() );
if( gm ) {
UUserProfile* object = ConstructObject<UUserProfile>(
gm->UPBlueprintClassName );
}
If you prefer, you can also use the NewObject function as follows:
UProfile* object = NewObject<UProfile>(
GetTransientPackage(), uclassReference );
How it works…
Instantiating a UObject class using ConstructObject or NewObject is simple.
NewObject and ConstructObject do nearly the same thing: instantiate an object of Blueprint class type, and return a C++ pointer of the correct type.
Unfortunately, NewObject has a nasty first parameter which requires you to pass GetTransientPackage() with each call. ConstructObject does not require this parameter with each call. In addition, ConstructObject provides you with more construction options.
Do not use the keyword new when constructing your UE4 UObject derivative! It will not be properly memory-managed.
There's more…
NewObject and ConstructObject are what the OOP world calls factories. You ask the factory to make you the object—you don't go about constructing it by yourself. Using a factory pattern enables the engine to easily track objects as they are created.