Creating a Blueprint Function Library is a Fun Way to Get Started with C++ Inside UE5
Getting started with C++ inside of Unreal Engine 5 can be a challenging and daunting task sometimes. However, I found creating a Blueprint Function Library is a fun way to start programming inside the engine.
Updated: Oct. 30, 2024
Software Versions: Unreal Engine 5.4.4 | Rider 2024.2.7
Project Name: MyProject
Writing C++ in Unreal Engine 5 can be an incredible and exciting experience that can really open up a lot options inside the engine. However, getting into UE5 C++ can be daunting at times. Even when I have to get back into it I get scared sometimes 😨. Jumping into the code base and then immediately trying to create custom classes can be difficult. Depending on experience, the learning curve can be steep and you'll typically crash the engine many times while programming and testing new features. Although C++ is great, we also don't want to abandon the wonderful world of Blueprints that are extremely powerful throughout Unreal projects. Balancing Blueprints and C++ in Unreal has always been a ballet where each project is different in how they handle their strengths and weaknesses. In my experience I found that a Blueprint Function Library is a great way to start writing C++ inside UE5. They're fun, simple, and pure and greatly help in reducing some of the complexity that can arise while working in Blueprints.
Epic has a great write up on Blueprint Function Libraries here. Overall they're a set of stateless functions that can be used throughout the project. A Blueprint Function Library can be a lot of fun to use because you get to continue using Blueprints while also writing some awesome C++ code. In the past I found that a Blueprint Function Library was a great place to reduce the large parts of my massive spaghetti interweaved Blueprint scripts that I somehow managed to shove all in one place.
The example in this post is using the BP_Door
Blueprint from the Content Examples and moving some of the logic into a Blueprint Function Library. This isn't the most practical example, the Blueprint is already great as it is, but I thought it be a fun example of how to extract some logic and write some C++.
I really like the BP_Door
Blueprint, it's simple and works very well. You can find the BP_Door
Blueprint in the Epic's Content Examples Project inside the Blueprints_Advanced
level. I Migrated the asset to my project so I could work on it without affecting the example and then I created a new C++ Blueprint Function Library.
For this quick exercise I wanted to extract some Blueprint logic away from BP_Door
and add it to a C++ function. Inside the Trigger Box's BeginOverlap
function I decided to rewrite some of the portions before and after the SwingDoor
timeline. Again, not the most practical example, the Blueprint is already very clean, but this technique can definitely help out when the Blueprint logic gets very large and becomes tough to manage through visual scripting.
Once inside the IDE the code was't too difficult to rewrite. I wrote two functions that accept a few arguments that just replicate what the Blueprint was already doing. I included the KismetMathLibrary
in the .cpp
file to utilize it's RLerp
function.
MyBlueprintFunctionLibrary.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyBlueprintFunctionLibrary.generated.h"
/**
*
*/
UCLASS()
class MYPROJECT_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
// Static functions do not require a target and they will appear in Blueprints when Context Sensitive is checked
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Door Functions")
static bool IsActorInFront(FVector ActorLocation, FVector OtherActorLocation, FRotator OtherActorRotation);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Door Functions")
static FRotator GetRotateValue(FRotator ActorRotation, float Alpha, bool OpenDirection, float RotateDegrees);
};
MyBlueprintFunctionLibrary.cpp
#include "MyBlueprintFunctionLibrary.h"
#include "Kismet/KismetMathLibrary.h"
bool UMyBlueprintFunctionLibrary::IsActorInFront(FVector ActorLocation, FVector OtherActorLocation, FRotator OtherActorRotation)
{
FVector NewLocation = ActorLocation - OtherActorLocation;
FVector UnrotatedVector = OtherActorRotation.UnrotateVector(NewLocation);
return UnrotatedVector.X > 0 ? true : false;
}
FRotator UMyBlueprintFunctionLibrary::GetRotateValue(FRotator ActorRotation, float Alpha, bool OpenDirection, float RotateDegrees)
{
float Direction = OpenDirection ? RotateDegrees : -RotateDegrees;
FRotator NewRotation = FRotator(0.0f, Direction, 0.0f);
FRotator FinalRotation = UKismetMathLibrary::RLerp(ActorRotation, NewRotation, Alpha, true);
return FinalRotation;
}
After writing these two functions and recompiling I was able to add them to the BP_Door
Blueprint. Next, I added a new float variable to BP_Door
called RotateDegrees
and defaulted the value to 90
that will be passed to the GetRotateValue
function. These two library functions are pretty Door Blueprint specific, so they're not very re-usable, but for this simple exercise it's fine, we're just having fun.
Replacing some of the Blueprint logic with the library functions make this Blueprint a little bit cleaner, but not by much. Again, not the most practical example, but this can help out when Blueprints get overwhelming with multiple if
statements or vector conversions.
Conclusion
When I have complex Blueprints that are getting difficult to manage I find it fun to create static pure functions that do most the heavy lifting. I don't have to recreate the entire Actor class or re-parent the Blueprint, I get to use all the wonderful features of Blueprints while also having fun with C++. Furthermore, Blueprint Function Libraries are great at getting your feet wet in writing C++ inside UE5 because they don't require as much overhead or learning as other UE5 classes. You can simply just start writing C++ and begin getting use to UE5's C++ coding style and just start having fun without having to worry too much about drastically changing your project's structure.
Harrison McGuire