虚幻引擎(UE4) 日志、打印运行时信息
概述
日志用于引擎及时反馈给我们运行时刻数据和信息。强大的用途不限于如下:
- 函数是否被调用
- 算法使用的什么数据
- 上报错误给开发组或者用户
- 特定时刻强制运行致命错误(如断言错误)以停止执行程序。
本章将介绍如何在虚幻引擎中输出日志。
目录
获取日志
-
游戏中
为了在游戏中能看到日志,你必须以“-Log”的方式运行游戏(创建一个编辑器快捷方式的可执行程序,并在后面加上 “-Log”),或者在游戏中控制台输入命令行"showlog" -
在编辑器中
日志信息被打印在“Output”窗口,Output窗口打开方式:Window -> Developer -> Output Log。
如果你使用编辑器和PIE,日志默认是可用的,因为在你的引擎 ini 文件里已经声明了 "GameCommandLine=-log"
如果还是看不到日志,请按上面的方式操作添加“-Log”命令行。
使用方法
UE_LOG(LogTemp, Warning, TEXT("my message"));
这种方式打印不需要指定自定义的日志类别,尽管这样做会让日志清晰和整齐。
日志详情级别
日志类别被用于控制那些被打印的内容,帮你更加清晰识别日志的重要等级。每个日志按照自己的级别来分类显示,开发者可以迅速查找到对应的日志内容。这些类别包括:编译时详情级别、默认的详情级别、ini详情级别和运行时详情级别:
-
Fatal(致命错误)
打印到控制台并写入日志文件,即使日志不可用/不打印也会导致崩溃。 -
Error
打印到控制台并写入日志文件,在日志文件中默认显示为红色 -
Warning
打印到控制台并写入日志文件,在日志文件中默认显示为黄色 -
Log
只打印写入日志文件中,不会打印到控制台。在编辑器的Output窗口也能看到。 -
Verbose
只打印写入日志文件中,不会打印到控制台。通常用来查看更详细的日志信息和调试 -
VeryVerbose
只打印写入日志文件中,不会打印到控制台。通常用来查看非常详细的日志记录,也会产生垃圾信息输出。
设置自己的日志类别
日志类别宏
分别在游戏头文件(YourGame.h)中声明DECLARE_LOG_CATEGORY_EXTERN,在源文件(YourGame.cpp)中定义 DEFINE_LOG_CATEGORY。
声明日志类别宏有三个参数,每个声明的日志类别都应该在.cpp文件中有一个定义。
DECLARE_LOG_CATEGORY_EXTERN(CategoryName, DefaultVerbosity, CompileTimeVerbosity);
- 参数CategoryName 是你定义的类别名。
- 参数DefaultVerbosity 如果在INI文件没有指定详情级别,这种类别下的日志都会被记录。
- 参数CompileTimeVerbosity 是要在代码中编辑的最大详情类别
只需要一个类别名字就能定义日志宏:
DEFINE_LOG_CATEGORY(CategoryName);
使用样例
你可以根据你的喜好来定义不用的日志类别
下面是一个有用的例子。
你可能在某个游戏系统中经常遇到问题,在调试中可能你想要更详细的日志,但是程序结束调试后,你又想要刚刚的日志记录,发现日志文件中有很多垃圾信息,你改怎么做?那就使用不用的日志类别。
Game.h
-
//普通日志
-
DECLARE_LOG_CATEGORY_EXTERN(LogMyGame, Log, All);
-
-
//游戏启动日志
-
DECLARE_LOG_CATEGORY_EXTERN(LogMyGameInit, Log, All);
-
-
//AI日志
-
DECLARE_LOG_CATEGORY_EXTERN(LogMyGameAI, Log, All);
-
-
//其他系统日志
-
DECLARE_LOG_CATEGORY_EXTERN(LogMyGameSomeSystem, Log, All);
-
-
//错误日志,通常可以通过日志定位到错误的位置
-
DECLARE_LOG_CATEGORY_EXTERN(LogMyGameCriticalErrors, Log, All);
Game.cpp
-
#include "MyGame.h"
-
-
//普通日志
-
DEFINE_LOG_CATEGORY(LogMyGame);
-
-
//游戏启动日志
-
DEFINE_LOG_CATEGORY(LogMyGameInit);
-
-
//AI日志
-
DEFINE_LOG_CATEGORY(LogMyGameAI);
-
-
//其他系统日志
-
DEFINE_LOG_CATEGORY(LogMyGameSomeSystem);
-
-
//错误日志。通常可以通过日志定位到错误的位置
-
DEFINE_LOG_CATEGORY(LogMyGameCriticalErrors);
下面是调用打印
-
//...
-
void UMyClass::FireWeapon()
-
{
-
UE_LOG(LogMyGameSomeSystem, Verbose, TEXT("UMyClass %s entering FireWeapon()"), *GetNameSafe(this));
-
//逻辑
-
UE_LOG(LogMyGameSomeSystem, Verbose, TEXT("UMyClass %s Attempting to fire."), *GetNameSafe(this));
-
if (CheckSomething())
-
{
-
UE_LOG(LogMyGameSomeSystem, Log, TEXT("UMyClass %s is firing their weapon with charge of %f"), *GetNameSafe(this), GetCharge());
-
}
-
else
-
{
-
UE_LOG(LogMyGameSomeSystem, Error, TEXT("UMyClass %s CheckSomething() returned false during FireWeapon(), this is bad!"), *GetNameSafe(this));
-
}
-
//其他打印
-
UE_LOG(LogMyGameSomeSystem, Verbose, TEXT("UMyClass %s leaving FireWeapon()"), *GetNameSafe(this));
-
}
-
-
void UMyClass::Tick(float DeltaTime)
-
{
-
UE_LOG(LogMyGameSomeSystem, VeryVerbose, TEXT("UMyClass %s's charge is %f"), *GetNameSafe(this), GetCharge());
-
if (something)
-
{
-
UE_LOG(LogMyGameSomeSystem, VeryVerbose, TEXT("Idk"));
-
}
-
if (somethingelse)
-
{
-
UE_LOG(LogMyGameSomeSystem, VeryVerbose, TEXT("Stuff"));
-
}
-
}
-
//...
格式化打印
打印一个 Message
UE_LOG(YourLog,Warning,TEXT("This is a message to yourself during runtime!"));
打印一个String
-
UE_LOG(YourLog,Warning,TEXT("MyCharacter's Name is %s"), *MyCharacter->GetName() );
-
-
//其中%s 需要匹配类型为TCHAR*, 所以使用 *FString()
打印Bool
UE_LOG(YourLog,Warning,TEXT("MyCharacter's Bool is %s"), (MyCharacter->MyBool ? TEXT("True") : TEXT("False")));
打印Int
UE_LOG(YourLog,Warning,TEXT("MyCharacter's Health is %d"), MyCharacter->Health );
打印Float
UE_LOG(YourLog,Warning,TEXT("MyCharacter's Health is %f"), MyCharacter->Health );
打印FVector
UE_LOG(YourLog,Warning,TEXT("MyCharacter's Location is %s"), *MyCharacter->GetActorLocation().ToString());
打印FName
UE_LOG(YourLog,Warning,TEXT("MyCharacter's FName is %s"), *MyCharacter->GetFName().ToString());
打印FString, Int,Float
UE_LOG(YourLog,Warning,TEXT("%s has health %d, which is %f percent of total health"), *MyCharacter->GetName(), MyCharacter->Health, MyCharacter->HealthPercent);
打印字体的颜色
灰色(普通日志信息)
UE_LOG(YourLog,Log,TEXT("This is grey text!"));
黄色(警告)
UE_LOG(YourLog,Warning,TEXT("This is yellow text!"));
红色(错误)
UE_LOG(YourLog,Error,TEXT("This is red text!"));
致命错误:采用主动崩溃保护机制
如果你希望某段代码被正确的运行,你可以在不该运行代码的地方抛出一个致命错误,这样可以帮你确保你的算法不会出错,非常有用。
但是它看上去是一个崩溃,但是不用担心,看看崩溃的堆栈信息或许能帮你找到出错的原因。
快速打印提示
这是一个更简单的打印技巧,你需要在你的文件中声明,并include到使用的文件里
#define print(text) if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 1.5, FColor::White,text)
PrintString
PrintText
PrintWarning
为了防止太多的相同打印,你可以将第一个参数设置为一个正数,UE4将会删除其他相同的打印内容,保持最新的日志信息。
其他打印方式
打印到屏幕
-
#include <EngineGlobals.h>
-
#include <Runtime/Engine/Classes/Engine/Engine.h>
-
// ...
-
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("This is an on screen message!"));
-
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Some variable values: x: %f, y: %f"), x, y));
打印到客户端控制台
按下"~"键打开UE控制台,如果您使用PlayerController类,您可以将消息打印到这个控制台,这样做的好处是,它是一个完全不同的日志空间,不需要在游戏外设置选项卡即可轻松查看
日志关键字
- [cat] = 命令操作的类别
- [level] = verbosity level(详情级别), 包括:none, error, warning, display, log, verbose, all, default
有用的控制台命令
- Log list - 列出所有的日志内别
- Log list [string] - 列出所有的日志内别,包括一个子字符串
- Log reset - 重置日志类别
- Log [cat] - 切换显示的类别
- Log [cat] off - 禁用日志类别
- Log [cat] on - 开启日志类别
- Log [cat] [level] - 设置日志类别的级别
- Log [cat] break - 在显示类别上切换调试断点
日志命令行
-
-LogCmds=\"[arguments],[arguments]...\" - 启动时刻执行的命令行
-
-LogCmds=\"foo verbose, bar off\" - 打开foo类别并关闭bar类别
环境变量
每一条命令行都可以通过环境变量 "UE-CmdLineArgs"设置
set UE-CmdLineArgs=\"-LogCmds=foo verbose breakon, bar off\" 在环境变量中设置开启foo类别,关闭bar类别
配置文件
在UE项目目录./Config/DefaultEngine.ini或者Engine.ini中设置:
-
[Core.Log]
-
global=[default verbosity for things not listed later]
-
[cat]=[level]
-
foo=verbose break
文章来源: blog.csdn.net,作者:呦呦鹿鸣.,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/zhang1461376499/article/details/113351948
- 点赞
- 收藏
- 关注作者
评论(0)