在软件项目中,日志一直扮演着一个及其重要的角色。程序员经常依赖它来定位问题,在某些不方便调试的情况下,日志甚至是唯一一个可以依赖的工具。虚幻作为一个游戏引擎,它的强大体现在各个方面,也包括日志系统。在本文里我就引擎提供的三种打日志的方式来介绍这一系统。
提到日志,大概我们第一个想到的就是在输出终端上打印的日志。对于这类日志引擎提供了UE_LOG宏来实现。UE_LOG不仅仅有了种类众多的预定义(Category)种类,还有日志级别(Verbosity)控制。预定义的日志种类声明可以查看CoreGlobal.h文件。我们选择LogTemp这个预定义的日志种类来举例,比如如下的代码:
UE_LOG(LogTemp, Log, TEXT("Hit, hit"));
UE_LOG(LogTemp, Warning, TEXT("Hit, hit"));
UE_LOG(LogTemp, Error, TEXT("Hit, hit"));
这段程序运行起来后会在引擎编辑器里的Output Log窗口输出这样的日志:
UE_LOG宏的第一个参数就是日志种类(Category),第二个是日志级别(Verbosity),剩下的就是日志内容了。我们可以看到编辑器根据日志级别的不同,特意用不同的颜色打印日志,以方便我们查看。当日志数量过多时,我们还可以根据种类(Category)对日志进行过滤,只查看我们感兴趣的类别。
除了使用引擎预定义的日志种类输出,我们还可以自定义日志种类(Category)。比如我们的模块叫FPSGame,我们可以在模块头文件上加上一个声明日志种类的宏:
DECLARE_LOG_CATEGORY_EXTERN(FPSGame, All, All)
然后在模块的CPP文件中加上定义日志种类的宏:
DEFINE_LOG_CATEGORY(FPSGame)
这样我们就可以用FPSGame这个日志类别来输出日志:
UE_LOG(FPSGame, Warning, TEXT("Hit, hit"))
用UE_LOG输出日志只会在编辑器的Output Log窗口里显示,但我们并不只是在编辑器里运行我们的游戏,引擎的开发者为我们也想到了这一点,给我们提供了一个在游戏屏幕上显示日志的函数:AddOnScreenDebugMessage。比如在代码里我需要在玩家往前/右移动时在屏幕上显示移动的数值,像下面这样做:
void AFPSCharacter::MoveForward(float Value)
{
FString DebugMsg = FString::Printf(TEXT("Move forward:%s"), *FString::SanitizeFloat(Value));
int32 key = 1;
GEngine->AddOnScreenDebugMessage(key, 1, FColor::Green, DebugMsg);;
}
void AFPSCharacter::MoveRight(float Value)
{
FString DebugMsg = FString::Printf(TEXT("Move right:%s"), *FString::SanitizeFloat(Value));
int32 key = 2;
GEngine->AddOnScreenDebugMessage(key, 1, FColor::Blue, DebugMsg);
}
当程序运行起来后,你就可以在游戏窗口左上角看到这样的显示:
需要提一下的是AddOnScreenDebugMessage的第一个参数是key值,用来控制屏幕上显示日志的唯一性的,也就是说key值相同的日志只会显示一个。另外就是在引擎版本4.19里这个函数有bug会导致日志在屏幕上显示不出来,假如你遇到这样的问题,升级到最新版本应该就好了。
除了在屏幕上显示日志,有时候我们还需要在游戏3D场景里也显示日志,比如我们在射击游戏里标注一下子弹飞行过程中碰撞到了那些位置,为了满足这样的需求,引擎特意提供了DrawDebugString这个函数,使用方式如下:
void AFPSProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
if ((OtherActor != NULL) && (OtherActor != this) && (OtherComp != NULL) && OtherComp->IsSimulatingPhysics())
{
OtherComp->AddImpulseAtLocation(GetVelocity() * 100.0f, GetActorLocation());
Destroy();
}
DrawDebugString(GetWorld(), Hit.ImpactPoint, "Hit", nullptr, FColor::Red, 2.0f, true);
}
这段程序运行起来后就会在子弹碰撞的地方都标上红色的“Hit”字样,帮助开发者定位子弹的运动轨迹:
以上就是虚幻引擎提供的日志功能了。有了这三种打日志的方式,作为使用者的我们要是使用得当,一定能让我们的开发事半功倍。