在UE中,经常由于测试的需要,需要临时添加一些辅助函数或者一些辅助代码,这些代码不太适合直接提交到项目里,因此这里开个文章作为记录,避免每次重头查阅资料。
1. 函数
1.1 堆栈打印函数
用于输出当前点的函数调用堆栈,实现代码给出如下:
#include "HAL/PlatformStackWalk.h"
void PrintCallStack()
{
ANSICHAR* StackTrace;
const SIZE_T StackTaceSize = 65535;
StackTrace = (ANSICHAR*)FMemory::Malloc(StackTaceSize);
StackTrace[0] = 0;
FPlatformStackWalk::StackWalkAndDump(StackTrace, StackTaceSize, 0);
FString StackTraceText(StackTrace);
TArray<FString> StackLines;
StackTraceText.ParseIntoArrayLines(StackLines);
UE_LOG(LogTemp, Error, TEXT("-----------Call Stack---------------------"));
for(FString& StackLine : StackLines)
UE_LOG(LogRHI, Error, TEXT("\t %s"), *StackLine);
}
2. 调试
2.1 关闭代码优化
UE引擎的代码优化开关跟普通Visual Studio项目的代码优化开关不太一样,这个开关是通过在Build.cs文件中进行定义来实现对单个模块的优化控制的:
如上图所示,当我们需要关闭某个模块的代码优化时,只需要在此模块所对应的ModuleRules子类的构造函数中添加:
OptimizeCode = CodeOptimization.Never;
即可关闭优化。
2.2 弹窗log
在真机上弹窗显示消息
FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, TEXT(
"Failed to find all required Vulkan entry points! Try updating your driver."), TEXT("No Vulkan entry points found!"));
2.3 屏幕信息打印
// Clear all screen messages
GEngine->ClearOnScreenDebugMessages();
// Add Screen Message
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, PosMsg);
2.4 调用命令行命令
// Enable Screen Message
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), TEXT("EnableAllScreenMessages"), GetWorld()->GetFirstPlayerController());
3. 类型相关
3.1 FString
3.1.1 FString转char*
FString FilePath("Good Enough");
char* Prefix = TCHAR_TO_ANSI(*FilePath);
4. 功能
4.1 文件IO
文件及路径操作,UE集成了一些函数可供使用,具体可以参考如下的一些Class:
1. FPaths Class
2. FFileManagerGeneric
4.2 文件引用
4.2.1 ThirdParty头文件引用
第三方库头文件引用需要通过宏进行包裹(HlslccHeaderWriter.cpp):
THIRD_PARTY_INCLUDES_START
#include "spirv_reflect.h"
THIRD_PARTY_INCLUDES_END
可能会遇到文件找不到的报错,可以打开对应Module的Build.cs文件,添加对应的Include Path(ShaderCompilerCommon.Build.cs):
PublicSystemIncludePaths.Add("ThirdParty/hlslcc/hlslcc/src/hlslcc_lib");
PublicSystemIncludePaths.Add("ThirdParty/SPIRV-Reflect/SPIRV-Reflect");
到这里还没结束,因为只有头文件而没有实现,会报错 unresolved external symbol xxx之类的,此时还需要添加对应的lib文件:
if (UnrealTargetPlatform.Win32 == Target.Platform || UnrealTargetPlatform.Win64 == Target.Platform) //decide the platform to package the binaries
{
PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "LibraryBinariesFolder", "Windows", "liblibrary.lib")); //the full path is "LibraryBinariesFolder/Windows/liblibrary.lib"
}
else if (UnrealTargetPlatform.Android == Target.Platform)
{
PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "LibraryBinariesFolder", "Android", "armeabi-v7a", "liblibrary.a")); //the full path is "LibraryBinariesFolder/Android/armeabi-v7a/liblibrary.a"
PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "LibraryBinariesFolder", "Android", "arm64-v8a", "liblibrary.a")); //the full path is "LibraryBinariesFolder/Android/arm64-v8a/liblibrary.a"
}
更多可以参考How to include any Third-Party library in Unreal Engine 4
4.3 其他
4.3.1 定时器
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYPROJECT_API AMyActor : public AActor
{
GENERATED_BODY()
public:
AMyActor();
protected:
virtual void BeginPlay() override;
private:
FTimerHandle TimerHandle;
};
#include "MyActor.h"
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
}
void AMyActor::BeginPlay()
{
Super::BeginPlay();
// Set the timer to call a lambda function after a 5-second delay
GetWorld()->GetTimerManager().SetTimer(TimerHandle, [this]()
{
UE_LOG(LogTemp, Warning, TEXT("Lambda function called!"));
}, 5.0f, false);
}
未完待续...