Visual Logger
捕获Actor的状态并在游戏或者编辑器中显示出来
Visual Logger是一个强大的调试工具,可以创建和记录游戏状态,并可视化显示出来,提供可在编辑器中查看游戏数据的功能。开发者可以在游戏会话中看到调试数据,也可以在游戏会话结束后在编辑器中查看数据记录。这让开发者更加容易解决游戏中难以追踪定位的、仅仅依靠玩家报告的和游戏画面提供的缺陷(Bugs)。在游戏中经常遇到哪些概率低且很难复现的缺陷,记录游戏数据以供后期查看显得特别重要。举个例子,一个游戏状态变量可能在某一帧导致发生我们不想看到的AI行为,记录发生错误片刻的数据可以提供给我们在后期调试参考的依据。
激活Visual Logger的方法:Windows > Developer Tools > Visual Logger。在虚幻4.7以上的版本,在控制台输出命令行"VisLog"也可以激活,如果你当前在编辑器中,Visual Logger视图也会自己打开。
上面图是在虚幻游戏《StrategyGame》中使用Visual Logger的例子。紫色的线指示了AI前进的路线,红色的定位标志显示了在时间轴上当前的位置点。
Visual Logger 视图简介
在编辑中记录了预先记录的游戏数据和状态,可供开发者在游戏后期随时查看记录的数据和状态。
Visual Logger 包含一个Actor列表记录了所有可视化的数据,一个记录了列表中当前选择的Actor在当前时间点的状态的视图、一个显示调试信息的输出文本窗口、一个时间条。
Actor列表
下图高亮区域显示了Actor列表信息。这里也提供了搜索功能。
Actor详情视图
采用UE_LOG宏收集的任何Actor数据都会显示在下图高亮区域。Visual Logger会显示当前列表中选择的Actor在当前时间轴位置的所有状态数据。捕获的数据可以被分类显示,你也可以在你的代码中自定义类别名,并且你也可以扩展这些类别。
在同一帧中从同一Actor进行多个可Visual Logger调用将覆盖先前捕获的数据。
文本输出窗口
文本输出窗口记录了当前帧的日志信息,并分类显示。重复的记录信息会显示在相同的类别里,同一帧的并且相同的数据会显示为一个列表。
时间轴
时间轴界面提供了一个滑动条,可以移动到你选择的时间轴位置,在下图中,Actor列表中选择了StrategyAIController_1,时间轴定位在23.53秒的位置,当你活动滑动条,文本输出窗口会显示当前选择的时间轴位置的数据信息。
添加Visual Logger 依赖项
有三种方法可以添加:
类型 | 输出描述 |
Actor | 当Actor存在的时候,会显示在Actor列表,并且会每帧更新。 |
Log消息 | Visual Logger记录的所有数据将会出现在文本窗口,仅仅是显示单帧数据。 |
Debug Shapes | 你可以在游戏世界中绘制各种各样的Shape图形,这些图形拥有多个参数,比如size尺寸和color颜色,图形会持续很多帧。 |
获取Actor状态的快照信息
要添加数据到Actor可视化调试列表,你首先要按照下面的方式实现接口类IVisualLoggerDebugSnapshotInterface:
class MYPROJECT_API AMyActor : public AActor, public IVisualLoggerDebugSnapshotInterface
这个接口类包含了一个函数GrabDebugSnapshot,默认没有任何的处理,此函数在激活了Visual Logger后会自动调用。你可以重写这个方法来收集日志数据。由于GrabDebugSnapshot函数只会在Visual Logger启动后才会运行,最好的方法是就是在使用此函数前加上宏条件判断,做法如下:
#if ENABLE_VISUAL_LOG
//~ Begin IVisualLoggerDebugSnapshotInterface interface
// Adds information about this Actor to the Visual Logger.
virtual void GrabDebugSnapshot(FVisualLogEntry* Snapshot) const override;
//~ End IVisualLoggerDebugSnapshotInterface interface
#endif
下面是一个第一人称游戏demo添加可视化日志记录的代码。此段代码在“GDC Sample”类别下添加了一个条目。条目被标记为“Projectile Class”,并包含角色在射击时产生的射弹类型。
#if ENABLE_VISUAL_LOG
void AGDCCharacter::GrabDebugSnapshot(FVisualLogEntry* Snapshot) const
{
Super::GrabDebugSnapshot(Snapshot);
const int32 CatIndex = Snapshot->Status.AddZeroed();
FVisualLogStatusCategory& PlaceableCategory = Snapshot->Status[CatIndex];
PlaceableCategory.Category = TEXT("GDC Sample");
PlaceableCategory.Add(TEXT("Projectile Class"), ProjectileClass != nullptr ? ProjectileClass->GetName() : TEXT("None"));
}
#endif
上面代码测试结果:
文本日志
你可以使用UR_LOG宏来记录日志并输出在Text输出窗口。文本输出窗口显示内容是基于帧的,所以只有当前帧记录的内容才会显示到此窗口。你你可以使用UE_LOG在任何地方记录日志, UE_LOG会自动识别是否支持Visual Logger,所以不用担心日志中是否需要判断上面曾提到的ENABLE_VISUAL_LOG宏。UE_LOG宏的参数关联了文本、日志类别、日志等级以及自己。
在下面的样例中,自定义的Character类使用UE_LOG宏来记录开火后射出物体的信息。
void AGDCCharacter::OnFire()
{
// 开火
if (ProjectileClass != NULL)
{
// 获取自身旋转角
const FRotator SpawnRotation = GetControlRotation();
// 炮口的偏移位置是在摄像机空间,所以就必要将炮口位置坐标从摄像机空间换算到世界空间的位置。
const FVector SpawnLocation = GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
UWorld* const World = GetWorld();
if (World != NULL)
{
// 在枪口生成一个炮弹
World->SpawnActor<AGDCProjectile>(ProjectileClass, SpawnLocation, SpawnRotation);
// 开始记录
UE_VLOG(this, LogFPChar, Verbose, TEXT("Fired projectile (%s) from location (%s) with rotation (%s)"),
*ProjectileClass->GetName(),
*SpawnLocation.ToString(),
*SpawnRotation.ToString());
}
}
}
在Visual Logger窗口中显示如下:
如果你需要记录重复的日志,请使用UE_VLOG_UELOG替换UE_LOG。
绘制调试图形
记录图形信息的功能是非常强大的特性,因为它帮我们可视化正在发生的数据状态。下图展示了Visual Logger支持的不同类型的调试图形:路径信息,圆柱体、圆锥体、胶囊体、和矩形。
下面的宏支持多种图形,每个宏都要求Actor拥有一个自身自带的形状,一个日志类别和日志级别、几个额外属性、图形定义参数和相关的文本。下面的表格里提供了多种可用的形状和每种形状额外的参数。
Shape | Description | Additional Parameters |
---|---|---|
| 一条像素粗细的直线. |
|
| 可变粗细的直线 |
|
| 球体 |
|
| 轴对称的正方形盒子. |
|
| 旋转的盒子 |
|
| 圆锥体 |
|
| 圆柱体 |
|
| 胶囊体 |
|
| 3D网格 |
|
| 2D 凸多边形 |
|
| 带有箭头的线段 |
|