日志(Logging)意味着在运行期间的某个时间保持事件、函数调用、变量值等的有序记录。这通常以文本的形式保存在日志文件中。日志对于Unreal应用开发的调试排错非常有帮助,本文涵盖UE4日志宏的语法、日志消息的格式化、自定义日志类别以及如何在屏幕输出日志等内容。
1、UE_LOG语法
下面是一个简单的日志消息示例:
UE_LOG(LogTemp, Warning, TEXT("Hello"));
要利用日志语句中获得输出,请确保在测试更改之前编译项目。
UE_LOG是将日志消息输出到日志文件中的宏。它采用的第一个输入参数是日志记录类别的名称。引擎中已经内置了许多这些类别,在 CoreGlobals.h 中定义。您还可以创建自己的自定义日志记录类别。稍后将描述这样做的过程,单击此处跳转到该部分。
UE_LOG 宏的第二个参数声明消息的详细程度。上例中的最后一个参数是日志消息内容,字符串也使用一些printf 格式说明符,以便添加更多参数。请参阅下面的一些格式示例。
如果你正在搜索出现在视口上的蓝图样式日志记录,请单击此处。
2、消息格式化示例
含FString参数的消息:
UE_LOG(LogTemp, Warning, TEXT("The Actor's name is %s"), *YourActor->GetName());
含布尔参数的消息:
UE_LOG(LogTemp, Warning, TEXT("The boolean value is %s"), ( bYourBool ? TEXT("true") : TEXT("false") ));
含整型参数的消息:
UE_LOG(LogTemp, Warning, TEXT("The integer value is: %d"), YourInteger);
含浮点型参数的消息:
UE_LOG(LogTemp, Warning, TEXT("The float value is: %f"), YourFloat);
含FVector参数的消息:
UE_LOG(LogTemp, Warning, TEXT("The vector value is: %s"), *YourVector.ToString());
含多个参数的消息:
UE_LOG(LogTemp, Warning, TEXT("Current values are: vector %s, float %f, and integer %d"), *YourVector.ToString(), YourFloat, YourInteger);
3、关于Unreal日志
日志记录意味着在运行期间的某个时间保持事件、函数调用、变量值等的有序记录。这通常以文本的形式保存在日志文件中。对于软件开发人员来说,它是一个非常宝贵的工具,尤其是在调试时,因为它可以提供有关代码在任何给定时刻正在做什么的详细信息。好的用例包括确保某些代码块正在执行、检查函数之间传递的数据值以及报告潜在问题。
4、访问UE4日志
使用 UE4 时,有几种不同的方式可以访问日志:
- 如果你的 Play-In-Editor 会话已经结束,可以在 YourProjectName\Saved\Logs 文件夹中找到该会话的完整日志。以前会话的日志也将在那里,可以在需要时访问。如果不知道你的项目在哪里,可以在 Epic Games 启动器中打开项目库,右键单击相关项目,然后选择在文件夹中显示选项。
- 在输出日志选项卡中的编辑器中播放时,可以实时查看日志输出。如果默认没有打开,可以在Window->Developer Tools->Output Log下找到。除了实时记录之外,此选项卡还将保留当前虚幻编辑器会话期间发生的所有播放会话的所有日志信息。
- 如果你有一个可执行文件,可以在其名称末尾创建一个带有 -Log 的快捷方式,以便在启动可执行文件时打开日志。
- 可以在游戏运行时按波浪号 (~) 键打开控制台,并通过键入控制台命令 showlog 并按 Enter 键访问日志。请注意,如果在 Play-In-Editor 会话期间执行此操作,单击 x 关闭日志将关闭你的虚幻编辑器会话。
5、虚幻引擎日志详细级别
在某些情况下,查看更少或更详细的日志输出很有用。日志详细级别允许轻松控制给定日志中存在的详细级别。如果特定的日志语句比编译时的详细程度更详细,则不会将其编译到游戏代码中。之后,整个日志的级别设置为默认详细程度,可以在 Engine.ini 文件中更改。可以通过命令行更改运行时详细程度。给定日志的某个详细级别,只有具有匹配或更低详细级别的日志消息才会打印到它。具有较高详细级别的消息将被忽略。
下表列出了所有可用的详细级别,从最低详细到最高:
Verbosity Level | Printed in Console? | Printed in Editor’s Log? | Notes |
---|---|---|---|
Fatal | Yes | N/A | Crashes the session, even if logging is disabled |
Error | Yes | Yes | Log text is coloured red |
Warning | Yes | Yes | Log text is coloured yellow |
Display | Yes | Yes | Log text is coloured grey |
Log | No | Yes | Log text is coloured grey |
Verbose | No | No | |
VeryVerbose | No | No |
每个日志语句声明它属于哪个日志类别以及它的详细级别。
6、自定义日志类别
创建自己的日志类别将使解析日志文件变得更加容易,因为你可以在“输出日志”窗口中切换日志类别的可见性。为项目中的每个主要系统创建一个新的日志类别通常是一个好主意,例如程序关卡生成器或者游戏模式。
你可以通过将这两个片段放在需要使用此日志类别的任何位置来定义新的日志类别。可以将它们放在他们自己的文件中,并在需要的地方#include 。这些应该在代码的顶层,而不是在任何函数或类中。
头文件:
DECLARE_LOG_CATEGORY_EXTERN(LogCustom, Log, All);
cpp文件:
DEFINE_LOG_CATEGORY(LogCustom);
头文件片段的语法是DECLARE_LOG_CATEGORY_EXTERN(CategoryName, DefaultVerbosity, CompileTimeVerbosity). DefaultVerbosity 是在 ini 文件或命令行中未指定详细级别时使用的详细级别。不会记录任何比这更详细的内容。CompileTimeVerbosity 是要在代码中编译的最大详细程度。任何比这更详细的内容都不会被编译。
上面片段中的值是你的日志类别的一个很好的起点。
通常会看到日志类别以Log 为前缀,但这不是必需的。
7、将消息打印到屏幕
严格来说,在运行时将消息打印到屏幕上不算作日志记录,因为消息不会保存在文件中。但是,在开发和/或调试时,它通常比使用日志消息更方便,因为它允许你在游戏窗口中查看消息,而无需为日志打开单独的窗口。从实时变量值到函数调用顺序的任何内容都可以通过这种方式轻松查看。
这是一个简单的字符串消息的示例:
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::White, TEXT("This message will appear on the screen!"));
第一个参数是消息的键(key)。如果 key 设置为 -1,则每次执行这行代码时,都会在屏幕上添加一条新消息。例如,如果将这个添加到Tick()函数中,屏幕很快就会充斥着这些消息流。如果键是正整数(键的类型是 uint64),则每条新消息都会用与其键相同的整数替换前一条消息。例如,如果调用上述函数Tick()并将其键修改为 1,则游戏中的屏幕上只会看到一条消息,因为每个新调用都会简单地替换它。
第二个参数是显示消息的时长,以秒为单位,它是浮点类型。
第三个参数是一个FColor 类型的参数,用来确定文本颜色。最好使用在游戏世界背景下易于阅读的颜色。最简单的方法是使用预定义的颜色常量,例如FColor::White. 有关可用颜色常量的完整列表,请参阅此官方文档页面的底部。
第四个参数是消息本身。请注意,整个字符串必须只占用一个参数,因此,有多个参数的情况下需要使用FString::Printf():
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Some variable values: x = %f, y = %f"), x, y));
AddOnScreenDebugMessage()还有两个可选参数。第五个参数是一个布尔值,用于确定新消息是出现在顶部(如果为真)还是底部(如果为假)。请注意,这仅适用于键值设置为 -1 的情况。第六个参数是确定文本比例的二维向量。如果打印到屏幕上的消息太小而难以阅读,或者它们太大并占用太多屏幕空间,这将非常有用。
Visual Studio 可能会在 GEngine 下划线并声称它是未定义的。但是,你无需显式包含 Engine.h 或 EngineGlobals.h 即可在任何类中使用它。尽管有红色下划线,它应该可以编译并正常工作。
8、将消息添加到视口统计子系统
UE4.26 添加了视口统计子系统,允许向当前视口添加消息,例如“需要重建灯光”和“蓝图编译错误”。以下代码示例是直接从此类复制粘贴的。只需检查此类以检查所有可用选项。
if (UViewportStatsSubsystem* ViewportSubsystem = GetWorld()->GetSubsystem<UViewportStatsSubsystem>())
{
// Bind a member function delegate to the subsystem...
FViewportDisplayCallback Callback;
Callback.BindDynamic(this, &UCustomClass::DisplayViewportMessage);
ViewportSubsystem->AddDisplayDelegate(Callback);
// ... or use inline lambda functions
ViewportSubsystem->AddDisplayDelegate([](FText& OutText, FLinearColor& OutColor)
{
// Some kind of state management
OutText = NSLOCTEXT("FooNamespace", "Blarg", "Display message here");
OutColor = FLinearColor::Red;
return bShouldDisplay;
});
}
原文链接:UE_LOG简明教程 — BimAnt