欢迎光临散文网 会员登陆 & 注册

UE4 AddOnScreenDebugMessage实现原理详解

2022-03-05 15:12 作者:冰冷的诗  | 我要投稿

今日被小伙伴问起这个函数

解决问题之后搜了搜网上的资料,发现解释的都太含糊了。如下:

某博客的解释

然而虚幻能做的并不止这么简单,并且这个解释也包含歧义(如何理解“相同的信息”)。于是仔细研究了一下这个函数,与大家分享一下。


老规矩,先说结论,再上代码:

虚幻用了两个容器来存储屏幕上的debug信息:

Engine.h

PriorityScreenMessages 是一个 Trray,由虚幻自己管理生命周期,不向外提供查询接口。

ScreenMessages 是一个 TMap,开发者可追踪到自己的debug信息,并且有配套的删除,修改等接口。

那么传入的这个参数 Key ,实际就是每条信息的身份标识。-1 表示没有标识,这些消息一次性交付,交付后脱离开发者控制。 而其他的 key,则每一个 key 标识一条消息,这也回答了开篇的问题(如何理解“相同的信息”),这个key 不仅仅是 0 这么简单,可以传其他的数来标识其他的信息。


所以不上源码的解析都是在刷流氓!下面上源码!


上述代码中的 if 分支非常清晰,

如果是 -1, 则不经过查询,用的是 PriorityScreenMessages ,根据 bNewerOnTop 决定插到头部还是尾部。

如果是其他数,则先查询 ScreenMessages ,有则改现有Message, 无则创建。


额外两点说明:

1. 这里虚幻有一个非常巧妙的操作。

UnrealEngine.cpp

我们看到当需要把Message显示在顶端的时候(确切地说是要把Message 插到 PriorityScreenMessages 尾部),虚幻没有直接用Insert,而是在PriorityScreenMessages尾部构建Message 对象,节省了一次内存开辟。

Array.h

2. 我们同时注意到,对 ScreenMessages ,虚幻并没有判断 bNewerOnTop ,这是为什么呢?因为TMap 是一个无序的容器,虽然TMap支持排序,但是这里虚幻并未对其排序(也没有必要),故有自己 Key 的 Messages在屏幕上的显示顺序是不固定。


那么虚幻又是如何管理这两个容器的呢?答案在UEngine::DrawOnscreenDebugMessages中。

UnrealEngine.cpp

由于代码太长,这里我折叠了PriorityScreenMessages ,处理逻辑是一样的。


红色框便是生命周期管理逻辑,虚幻用了一个 TFrameValue 类型的变量 HasUpdatedScreenMessages 来标记每一帧是否已经计算过时间了。TFrameValue的特性是当前帧设置过的值会在下一帧自动失效。以确保同一帧打印多次debug,时间也只会被计算一次。


黄色框是计算屏幕位置逻辑,这里不展开讲。


蓝色框这里回应一下前文,我们看到虚幻并未对 ScreenMessages 做排序,故bNewerOnTop在此没有意义。


以上全为阿婆猪个人研究代码的结论,如有错误,欢迎大佬批评指正。


文(zhuang)艺(bi)范(fan)的结束语还没想好,小伙伴们有想法的话,可以评论区对个线。

UE4 AddOnScreenDebugMessage实现原理详解的评论 (共 条)

分享到微博请遵守国家法律