C++/Functions
Usage of Asynchronous and Threaded Functions in Unreal C++.
Takes a while to get used to and can be rather frustrating without any prior knowledge.
The two important things for Logging are:
UE_LOG(LogTemp, Warning, TEXT("Message")); // logs to the console
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Message"))); // prints message on screen
A good ressource (not including all edge cases) can be found HERE.
General: Casting
This is an example on how to get a Scene Component and than cast to it (cause we know it's a camera) to get its information.
In this case: we are a Scene Component attached to another Scene Component, which we know is a camera.
USceneComponent* ParentComponent = this->GetAttachParent();
const UCameraComponent* ParentCamera = Cast<UCameraComponent>(ParentComponent);
Additionally, the regular C++ style casting works as well. Here an example to go from a float to an int.
float FloatValue = 42.f;
int32 IntegerValue = static_cast<int32>(FloatValue);
Getter: Get World Context
Sometimes a static function requires a UWorld reference, like for example printing text to the screen, line-traces etc.
UWorld* World = GEngine->GameViewport->GetWorld();
Getter: Get Components by Class (from Actor)
If you need to get Components from an Actor, use the following:
TArray<USceneComponents*> Components;
this->GetComponents(Components);
The GetComponents() function will automatically get the correct Class and filter by it.
Getter: Get Actor of Class (from World)
If in the World you need to find an Actor by Class, use the following ():
AActor* CustomActor = UGameplayStatics::GetActorOfClass(
WorldContextObject, // UWorld*
ACustomActor::StaticClass()
);
ACustomActor* CustomActorReference = Cast<ACustomActor>(CustomActor);
Getter: Get Game Time
How to get the GameTime in seconds since BeginPlay:
double CurrentGameTime = GEngine->GameViewport->GetWorld()->GetTimeSeconds(); // get the game time
UFunction: Run External Executable
To start an executable within the Project/Game folder:
const FString RelativePath = FPaths::GameSourceDir() + "MyExecutable.exe";
const bool FileExists = FPaths::FileExists(RelativePath);
FString FullPath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*RelativePath);
const TCHAR* ProcPath = *RelativePath;
if (FileExists)
{
auto CommProc = FPlatformProcess::CreateProc
(
(ProcPath),
TEXT(""),
true,
false,
false,
nullptr,
0,
nullptr,
nullptr
);
}
To quit the executable (may not work, not yet sure why):
TerminateProc(CommProc);
UFunction - Specifier: Pass By Reference
If you want to edit values of variables directly in C++ using references from Blueprint, use the following as an example:
UFunction(BlueprintCallable)
static void EditInt(UPARAM(ref) int& EditorInt);
Now if you change the variable in C++, it'll also change the variable in Blueprint, because it's using a reference as input.
The important part here is:
UPARAM(ref)
before the Variable Reference.
If you use it without that line, it'll be shown as an output-line in Blueprint.
UFunction - Specifier: Deprecated
If you want to declare one of your UFunctions as deprecated, use the following metadata specifiers:
UFunction(
meta = (DeprecatedFunction, DeprecationMessage = "Insert reason why it's deprecated and what to do."))
Info: BlueprintCallable, Tooltip etc. have been left out in this example. Please do not forget about them. ;-)
UFunction - Specifier: Return Value Name
If you want the return value within a function to be named, instead of it just being displayed as return value:
UFunction(
meta = (ReturnDisplayName = "Delay"))
Now your return value will be displayed as "Delay" for the output pin. Important: really only does work for functions with an actual return value, that are not void!
UFunction - Exec Pins: Bool
There is a pretty nifty way to add a true and false exec pin to any UFUNCTION.
In this example we put in a pointer to an AActor and check, if it is valid and does not point to a nullptr.
Now to add the exec pins:
//.h
UFUNCTION(BlueprintCallable, meta = (ExpandBoolAsExecs = "IsValid"))
static void IsActorValid(AActor* Actor, bool& IsValid);
Now for the cpp file:
//.cpp
void AYourClass::IsActorValid(AActor* Actor, bool& IsValid)
{
if (Actor != nullptr)
IsValid = true;
else IsValid = false;
}
As soon as you define the IsValid, the execution pin in Blueprint will be triggered. This way you don't need to use a Branch or any other comparison, since it's already in here.
UFunction - Event: Custom Event
Example:
// .h
UFUNCTION((BlueprintImplementableEvent, BlueprintCallable, Category = "MyCategory")
void DoStuff();
This type of event/function is basically the same, as if you were to add a Custom Event via Blueprint.
To use it within Blueprint, simply right click and search for it. Voila!
But why use this instead? Well, in C++ it can easier be handled, categorized and called via C++ as well.
UFunction - Event: Custom Event with Variable(s)
Example, if you want a Custom event to use a Variable.
UFUNCTION((BlueprintImplementableEvent, BlueprintCallable, Category = "MyCategory")
void DoStuff(int32);
UFunction - Event: Custom Event with FString
Compared to other Variables, FString won't work out of the box. Long story short: to make it work, use the following:
UFUNCTION((BlueprintImplementableEvent, BlueprintCallable, Category = "MyCategory")
void DoStuff(const FString &MyString);
UFunction - Event: Call in Editor
Example:
// .h
FLinearColor RandomColor; // Define Random Color
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, CallInEditor, Category = "MyCategory")
void RandomColor();
// .cpp
void AMyClass::RandomColor_Implementation()
{
RandomColor = FLinearColor(
UKismetMathLibrary::RandomFloat(),
UKismetMathLibrary::RandomFloat(),
UKismetMathLibrary::RandomFloat(),
1.f);
}
This type of event/function will be displayed as a Button in the Details Panel of the Actor.
On click, it will do something: here create a random color (not used in this example).
Important: BlueprintNativeEvent will require it to be defined in C++, as of what to do when pressed (hence the .cpp file above).
If however you want it to be a Custom Event that can be used in Blueprint Graphs, use "BlueprintImplementableEvent" instead of "BlueprintNativeEvent". It then also won't require a definition in the .cpp file.
UFunction - Override Event: ConstructionScript (Overriding Members)
virtual void OnConstruction(const FTransform& Transform) override;
UFunction - Override Event: EndPlay (Overriding Members)
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFunction - Override Event: Tip for Jetbrains Rider
In your .h file, right click anywhere: "Show Context Actions"/"Generate Code..."/"Overriding Members".
With "Ctrl + F" search for what you need (or scroll down), select box and click "OK".
UFunction - template <typename>
What templates are in C++ is a bit too much to cover here, but as an example on how to use typename templates, here's a good example.
Lets say, you created a fixed size TArray and want to call a function, that returns its length, that should then be printed to the screen:
TArray<TObjectPtr<AActor>, TFixedAllocator<16>> MyFixedArray {nullptr, nullptr, nullptr};
GEngine->AddOnScreenDebugMessage(
-1, 10.f, FColor::Red, FString(
"Length: " + FString::FromInt(GetArrayLength(MyFixedArray))));
In the .h file, create the following function definition:
template <typename T>
static int32 GetArrayLength(TArray<TObjectPtr<AActor>, T> &Array);
In the .cpp file, create the function itself:
template <typename T>
int32 UCPPSC_Systems_Projectiles::GetArrayLength(TArray<TObjectPtr<AActor>, T> &Array)
{
return Array.Num();
}
Note: There is not .cpp required, a FORCEINLINE will also work, so that the function only lives within the header file.
Latent Action - Delay/Timer (Lambda)
Example:
float LoopDaly = 3.f;
bool LoopTimer = false;
FTimerHandle TimerHandle;
GetWorld()->GetTimerManager().SetTimer(TimerHandle, [&]()
{
UE_LOG(LogTemp, Warning, TEXT("This text will appear 3 seconds after execution and won't loop"));
}, LoopDaly, LoopTimer);
Here we use the Timer with a Lambda Function to display something after a certain amount of time.
A very good blog describes it in more detail: GeorgysBlog
Latent Action - Delay/Tick
Example for setting a Value for a Variable. The function itself is:
void GetAndSetActorTransform()
{
LastKnownVehicleLocation = this->GetActorTransform(); // LastKnownVehicleLocation is an FTransform stored somewhere else
}
Now to call the function after one Tick:
GetWorld()->GetTimerManager().SetTimerForNextTick(this, &ThisClass::GetAndSetActorTransform);