How to Optimize Performance in Unreal Engine 5

Nu Makes Games
28 Jan 202417:40

Summary

TLDR本视频介绍了如何使用虚幻引擎(Unreal Engine)的主要性能分析工具Unreal Insights来诊断和修复游戏中的性能问题。首先,视频展示了如何使用Unreal Insights进行追踪,并通过时间轴视图和火焰图来分析性能数据。接着,通过一个实际案例,展示了如何通过添加书签和CPU分析器范围来标记代码中的关键部分,从而定位性能瓶颈。案例中,开发者在时间回溯项目中遇到了性能瓶颈,通过分析发现,问题出在调试绘制API的过度使用上。为了解决这个问题,开发者采用了一种新的可视化组件,该组件继承自实例化静态网格组件,通过优化后的方法显著提升了性能,将帧率从20帧每秒提升到120帧每秒。视频最后鼓励观众在GitHub上查看代码,并提供了对回放项目的进一步了解。

Takeaways

  • 📈 **Unreal Insights工具介绍**:Unreal引擎的内置性能分析工具Unreal Insights功能强大,可用于诊断和修复游戏中的性能问题。
  • 🔍 **性能瓶颈分析**:通过实际案例分析,展示了如何使用Unreal Insights来定位并解决游戏性能瓶颈。
  • 🛠️ **性能优化实践**:作者分享了在其时间回溯项目中遇到的性能问题,并通过优化解决了帧率下降的问题。
  • 📊 **火焰图和时间线视图**:Unreal Insights提供了火焰图和时间线视图,帮助开发者深入理解游戏运行时的性能状况。
  • ⏯️ **实时追踪与回放**:开发者可以实时开始和停止追踪,查看游戏运行时的性能数据,并进行回放分析。
  • 📸 **书签与截图功能**:在追踪过程中,可以使用书签和截图功能标记重要时刻,方便后续分析。
  • 📝 **代码标记与注释**:通过在代码中添加书签和CPU分析器范围,可以在Unreal Insights中更清晰地看到性能影响。
  • 🔧 **性能问题的根源**:通过深入分析,发现性能问题并非最初预期的原因,而是由于后台线程中的渲染工作导致的。
  • 🚀 **新解决方案的提出**:作者通过重构代码,使用实例化静态网格组件替代了调试绘制管道,显著提升了性能。
  • 🎨 **自定义可视化组件**:创建了一个新的可视化组件,该组件继承自实例化静态网格组件,用于更高效地处理状态快照。
  • 📦 **资源与社区贡献**:作者将代码上传至GitHub,鼓励社区使用并根据需要进行修改,以促进共同进步。

Q & A

  • Unreal引擎的性能分析工具是什么?

    -Unreal引擎的性能分析工具是Unreal Insights,它非常强大,可以帮助用户诊断和修复游戏中的性能问题。

  • 如何开始在Unreal Insights中捕获追踪信息?

    -在Unreal Insights中,点击Trace菜单旁边的按钮开始追踪,该按钮变为红色表示正在追踪。

  • 在Unreal Insights中,如何查看捕获的追踪信息?

    -在Session Browser中查看所有捕获的追踪信息,双击一个追踪条目可以启动Unreal Insights并查看性能信息。

  • 在Unreal Insights的哪个视图中可以查看帧的时间线和性能数据?

    -在Unreal Insights的Timing View或Timing Pane中可以查看帧的时间线和性能数据。

  • 使用Unreal Insights时,如何快速切换到紧凑视图?

    -在Unreal Insights中,可以通过敲击键盘上的'C'键快速在全视图和紧凑视图之间切换。

  • 如何在Unreal Insights中对特定帧进行详细分析?

    -在Timing View中,可以左键点击想要分析的帧,然后按'F'键将时间线视图聚焦到该帧上进行详细分析。

  • Unreal Insights中的火焰图是什么?

    -火焰图是一种性能分析工具,它从上到下展示了不同函数的调用关系和耗时,帮助开发者理解程序的性能瓶颈。

  • 如何使用Unreal Insights来优化游戏性能?

    -通过分析Unreal Insights提供的帧时间线、火焰图和性能计数器等信息,找到性能瓶颈,然后对代码进行优化。

  • 在Unreal Insights中,如何捕获游戏运行时的性能数据?

    -可以在编辑器中运行游戏,并通过传递命令行参数(如'-Trace=default')来捕获性能数据。

  • 如何使用Unreal Insights来记录和回顾性能问题?

    -可以使用Unreal Insights的Bookmark和Screenshot功能,在遇到性能问题时快速记录当前状态,并在分析时回顾。

  • 在Unreal Insights中,如何查看和分析不同线程的性能数据?

    -在Unreal Insights的线程视图中,可以选择不同的线程进行查看,包括GPU线程、游戏线程、渲染线程和工作线程等。

  • 在Unreal Insights中,如何查看特定函数的调用者和被调用者?

    -在Counters和Timers视图中,选择特定的函数,可以查看该函数的inclusive和exclusive时间,以及它的调用者和被调用者。

Outlines

00:00

😀 Unreal引擎性能诊断工具介绍

本段介绍了Unreal引擎的主要性能分析工具Unreal Insights的强大功能。讲解者展示了如何使用该工具来诊断和修复游戏中的性能问题。首先,通过编辑器底部的Trace功能启动Unreal Insights,然后通过Session Browser查看捕获的Trace。讲解者还介绍了如何使用火焰图来查看不同线程的性能数据,并通过时间轴查看帧的时间消耗。此外,还介绍了如何使用热键C在完整视图和紧凑视图之间切换,以及如何查看日志和计时器等其他功能。

05:00

🔍 性能瓶颈分析与实例

讲解者通过一个实时案例,展示了如何使用Unreal Insights来分析和解决性能瓶颈问题。他提到了一个时间回溯项目,当开启调试可视化功能时,帧率会大幅下降。通过添加书签和CPU分析器范围来标记关键操作,并使用火焰图来识别性能瓶颈。发现问题后,讲解者通过进入引擎源代码并添加额外的检测来进一步确认性能瓶颈的原因。

10:00

🛠️ 性能问题的解决策略

在确定了性能瓶颈后,讲解者采取了一种新的方法来解决性能问题。他放弃了使用调试绘图管道,转而创建了一个新的组件,该组件继承自实例化静态网格组件。通过这个新组件,他能够显著提高性能,即使在打开时间线可视化时,帧率也能保持在120 FPS。此外,讲解者还介绍了如何使用Unreal的建模工具来创建简单的网格,用于性能优化后的可视化。

15:02

📚 代码分享与总结

最后,讲解者总结了Unreal Insights的使用,并鼓励观众通过YouTube的互动功能来支持视频。他还提到了将代码分享到GitHub上,以便其他开发者可以学习和使用。此外,讲解者还提到了之前关于时间回溯项目的详细介绍视频,并以友好的告别结束了本视频。

Mindmap

性能诊断
问题定位与修复
工具功能
通过编辑器底部启动
捕获追踪数据
实时显示性能信息
使用方式
Unreal Insights 工具介绍
帧率下降至20 FPS
调试可视化功能导致性能下降
时间回溯项目性能瓶颈
添加书签和CPU分析器范围
火焰图分析
帧时间分析
性能分析过程
性能问题实例分析
使用实例化静态网格组件
优化SetInstancesFromSnapshot函数
从调试绘制API迁移
帧率锁定在120 FPS
大幅减少帧渲染时间
减少组件Tick时间
性能提升效果
性能优化策略
运行独立模式进行分析
使用命令行参数进行追踪
利用快照和屏幕截图进行问题定位
额外的性能分析技巧
代码将上传至GitHub
鼓励社区使用和改进
代码共享与社区贡献
Unreal Engine 性能分析
Alert

Keywords

💡Unreal Engine

Unreal Engine 是一款广泛使用的3D游戏引擎,它提供了创建复杂和高质量的游戏内容所需的工具和功能。在视频中,Unreal Engine 被用来开发具有时间回溯机制的游戏原型,并且是性能分析的主要平台。

💡性能问题

性能问题通常指的是软件或系统在运行时出现的效率低下、响应慢或帧率下降等问题。视频中提到了游戏在开启某个调试功能后帧率大幅下降,这正是性能问题的体现。

💡Unreal Insights

Unreal Insights 是 Unreal Engine 提供的一个强大的性能分析工具,它可以帮助开发者诊断和解决游戏中的性能问题。视频中详细介绍了如何使用 Unreal Insights 来追踪和分析性能瓶颈。

💡帧率(FPS)

帧率,即Frames Per Second的缩写,是衡量视频和游戏运行流畅度的一个关键指标。视频中提到了游戏在某个状态下帧率从每秒200帧下降到每秒10帧,说明了性能问题对帧率的影响。

💡调试(Debugging)

调试是软件开发过程中用于识别和解决代码中错误或问题的过程。在视频中,开发者使用 Unreal Insights 进行调试,以找出导致性能下降的原因。

💡火焰图(Flame Graph)

火焰图是一种用于可视化程序运行时性能分析数据的图表,它能够展示程序中各个函数的执行时间和调用关系。视频中使用了火焰图来分析游戏线程中的性能瓶颈。

💡时间回溯(Time Rewinding)

时间回溯是一种游戏机制,允许玩家回放或逆转游戏内的事件和状态。视频中的开发者正在开发一个具有时间回溯功能的原型游戏,并且遇到了性能问题。

💡性能瓶颈

性能瓶颈指的是系统中导致性能下降的特定部分或环节。在视频中,通过分析发现,使用调试绘图API时,背景工作线程上的渲染工作是造成性能瓶颈的主要原因。

💡实例化静态网格组件(Instanced Static Mesh Component)

实例化静态网格组件是 Unreal Engine 中用于高效渲染大量相同网格实例的一种组件。视频中,开发者通过使用该组件替代调试绘图,成功解决了性能问题,保持了游戏的高帧率。

💡调试绘图API(Debug Drawing API)

调试绘图API是一组用于在游戏开发中可视化调试信息的工具,如绘制点、线和框等。虽然对于调试很有用,但视频中提到,过度使用这些工具会导致严重的性能问题。

💡性能优化

性能优化是改进软件或系统性能的过程,以提高效率和响应速度。视频的后半部分展示了开发者如何通过改变可视化方法,从使用调试绘图API转移到使用实例化静态网格组件,从而优化了游戏性能。

Highlights

Unreal Engine的内置性能分析工具Unreal Insights功能强大,可用于诊断和修复游戏性能问题。

通过Unreal Insights的会话浏览器可以查看所有捕获的跟踪信息。

使用火焰图可以深入了解不同线程中的函数调用及其耗时。

时间轴视图允许用户通过鼠标滚轮缩放和拖动来查看不同时间段的性能数据。

CPU和GPU菜单提供了过滤选项,允许用户关闭不需要查看的线程。

使用热键C可以在完整视图和紧凑视图之间切换,以查看性能数据。

日志视图显示了重要事件和时间戳,双击可以跳转到时间轴上的特定位置。

计时器是分析每帧发生事件的有用工具,可以查看包含时间和独占时间。

通过快照功能可以捕获当前的性能跟踪状态,即使没有主动跟踪。

在性能跟踪时可以添加书签和截图,以便记录特定时刻的性能状态。

为了获得更准确的游戏性能数据,可以在独立模式下运行Unreal Insights。

通过添加书签和CPU分析器范围,可以在Unreal Insights的时间轴视图中标记代码的特定部分。

性能瓶颈分析揭示了调试绘制API在启用时会导致帧率大幅下降。

通过Unreal Engine源代码添加额外的检测,可以更深入地了解性能瓶颈的具体原因。

通过从调试绘制管道转移到实例化静态网格组件,显著提高了性能并解决了帧率下降的问题。

使用实例化静态网格组件的新解决方案,帧率在启用时间线可视化时保持在120 FPS。

新的视觉组件通过标准Unreal网格绘制管道,大大减少了每帧的绘制时间。

作者将所有相关代码上传至GitHub,供有兴趣的人学习和使用。

Transcripts

00:00

welcome friends I'm new all game

00:02

projects have to deal with performance

00:03

issues budgets get blown frame targets

00:06

are missed and FPS tanks today's video

00:10

has two parts first we're going to look

00:12

at unreal's Main profiling tool unreal

00:15

insights is super powerful I'll show you

00:17

how it works and I'll teach you how to

00:18

diagnose and fix perf problems in your

00:20

game second we're going to look at a

00:23

real world example I've got a nasty perf

00:26

bottleneck in my time rewinding project

00:28

why is my game running at 20 frames per

00:31

second we're going to profile it to find

00:33

out and then we're going to fix it let's

00:36

get started unreal insights and tracing

00:38

functionality now live down in the

00:40

bottom right of the editor if you're in

00:42

an older version of the engine you'll

00:43

need to look around in the tools menu to

00:46

launch unreal insights we click on trace

00:48

and then go to Unreal insights session

00:51

browser this will pull up the session

00:53

browser which shows all of the traces

00:55

that we've captured if we've never

00:57

captured a trace it's completely empty

00:59

to Capt capture a trace we click the

01:01

button next to the trace menu to start

01:03

tracing that will turn red which shows

01:05

us that we're tracing and if we look at

01:07

the session browser we now see that we

01:09

have an entry its status is live and the

01:11

file size is rapidly increasing I'm

01:14

going to go ahead and stop tracing

01:16

before I look at my actual Trace file

01:19

with that done we can doubleclick on the

01:22

entry and this will launch on real

01:24

insights the insights application shows

01:27

us a ton of performance information

01:29

across a of different panes and we will

01:31

go through everything but we're mostly

01:33

going to be looking at this timeline

01:35

view or this timing view here in the

01:37

center within the timing pane you can

01:40

zoom in and out by using the mouse wheel

01:43

and you'll notice right away that my

01:45

editor has been running for quite a

01:47

while because I I went and got lunch and

01:49

left it up you can pan left and right by

01:52

clicking and dragging and you can zoom

01:55

back in by scrolling in within this view

01:59

we have a bunch of different tracks so

02:01

at the top here I have a GPU track I

02:03

have a track for my game thread track

02:06

for the rhi thread the render thread a

02:08

bunch of worker threads basically every

02:10

thread that is running in my editor

02:13

process and for each track we have a

02:17

flame graph so if you've never used a

02:19

flame graph before it basically goes top

02:22

to bottom and we can look here at the

02:24

top and we can see okay we have a frame

02:26

on the game thread within that frame we

02:29

ticked the world we drew the viewport

02:33

slate ticked that slate tick called

02:35

slate draw Windows which turns around

02:38

and called slate prepass so on and so

02:40

forth so we can basically drill into a

02:42

bunch of deeper calls and as long as

02:45

those calls are instrumented we can see

02:47

what they were doing and how much time

02:49

they spent in this top pane we have

02:52

timings for all the different frames in

02:55

our capture the bigger the bar the

02:58

longer the frame so if I wanted to look

03:00

at this one fat frame I can see it took

03:03

52 1 12 milliseconds which is about 19

03:06

frames per second I can left click on

03:09

that to jump to it and then if I press

03:11

the F key it's going to focus my

03:14

timeline view to look at that frame

03:16

specifically so here I can see I

03:18

actually spent 26 milliseconds pumping

03:20

Windows messages this is probably well I

03:23

don't know what was going on there I

03:25

would need to to drill in but this is a

03:26

really long frame along the top view of

03:29

timing we have a timeline which is the

03:31

time since the process started we have a

03:33

bunch of dropdowns which allow us to

03:35

turn tracks on and off so for some

03:37

reason I didn't want to look at say the

03:42

game thread I can just turn that off and

03:43

turn it back on note for something to

03:46

show up in this list I have to be

03:48

capturing it and we'll we'll talk about

03:49

how you can figure what you're capturing

03:52

a little bit later the CPU GPU menu also

03:55

gives you groupings to filter so if I

03:58

want to turn off all the background

03:59

workers I can make them disappear like

04:01

that other has some additional things

04:04

that we can look at plugins has some

04:06

other special things as well but

04:08

basically this is just allowing us to

04:10

turn things on and off for filtering

04:12

another hotkey that is super useful is

04:15

you can tap C to toggle between full

04:18

View and compact view so if I wanted to

04:21

get a compact picture of everything that

04:22

was going on I can tap see and you can

04:25

look for basically big chunks of color

04:28

that might be interesting to into and to

04:31

go back to the full view we just tap C

04:34

again in addition to the timing view

04:37

down at the bottom here we have a view

04:40

of logs and any important events and if

04:44

we doubleclick it will take us to that

04:46

position in the timeline so that we can

04:47

drill in over on the right we have

04:50

counters and timers I find timers are

04:52

generally the most useful if I want to

04:54

look at what happened in a frame I can

04:57

click on any of the tracks in my flame

04:59

graph

05:00

that will select it in the timer view I

05:02

can look at inclusive and exclusive time

05:05

and I can also get a full picture of who

05:08

called whatever my selection is so

05:10

that's callers we can see here that

05:12

engine Loop tick called frame which

05:14

called slate tick which called slate

05:15

draw Windows which called slate prepass

05:18

and I can also look at Coles which is

05:20

everything that the thing I have

05:22

selected calls in this case slate

05:25

prepass has widget inv validate called

05:27

14 times but these timings are all all

05:30

tiny 4 and 1/2 micros seconds so there's

05:34

a whole bunch of stuff going on in slate

05:36

prepass that that isn't instrumented and

05:38

if I wanted to investigate this what I

05:40

would begin doing is instrumenting that

05:43

code path and and seeing the details of

05:45

what is going on a couple other cool

05:48

things that we can do here I can take a

05:52

snapshot there is a continuous running

05:54

buffer in the editor and when we click

05:56

this button it will snap that buffer and

06:00

create a trace just with those details

06:03

so this is useful if like let's say I'm

06:05

playing the game I have a big perf hitch

06:07

but I wasn't actively tracing I can take

06:10

a snapshot to see what was there and

06:12

then you know open it up just like our

06:15

first trace and we we could see what was

06:17

going on few other things tracing

06:21

there's a whole bunch of different

06:23

channels that we can choose what we want

06:24

to look at right now I am using the

06:27

default so CPU GPU some regions

06:31

bookmarks some other things while a

06:34

trace is

06:35

running we can capture bookmarks and

06:38

screenshots which I'll show you so first

06:40

let me do a bookmark which I can do from

06:43

this menu and I can also do a screenshot

06:45

from this menu or press contrl plus F9

06:49

I'm going to stop my Trace I'm going to

06:51

come back to the session browser we're

06:54

going to look at our most recent

06:57

trace and on this this timeline

07:01

view once we get back to where we were

07:04

you will see hey there's a bookmark here

07:06

with a timestamp and that will also show

07:08

up in our log view here so that was when

07:11

I pressed that bookmark button and that

07:13

gives me a clear visual indicator of

07:15

what was going on there I also have the

07:19

screenshot right here on this timeline

07:22

so if I hit a bug or a performance issue

07:25

and I wanted to take a screenshot so

07:28

that I could remember what was going on

07:29

at that point in time we can do that

07:31

with Control Plus F9 while tracing and

07:33

similarly that is also down here in our

07:35

log view so this allows us to really

07:38

explore and get a full view of what

07:41

unreal was doing and we can look

07:44

retroactively we can make changes we can

07:47

measure things over

07:49

time other things that are useful to

07:51

know running in the editor we have a

07:54

whole bunch of stuff running that is not

07:56

our game if we want really

07:58

representative person CF of just what

08:00

our game is doing we can either build a

08:03

build cook and package and then run

08:06

unreal insights against that or we can

08:09

run against Standalone mode in both

08:12

cases what we need to do is pass an

08:14

additional argument as a command line

08:17

parameter the structure of that command

08:19

line argument I believe is Dash Trace

08:24

equals default for what I was capturing

08:26

before but you can also provide a comma

08:29

separated list of arguments like CPU GPU

08:33

for the individual tracks that we want

08:35

to capture so I'm going to try Trace

08:37

equals

08:38

default and then I am going to switch

08:41

this to Standalone game we're going to

08:44

run that and with any luck we should see

08:46

that session pop up and we

08:49

do

08:51

so right here I've got unreal insights

08:54

running I also have the game coming up

08:57

my game is now up I've lost my mouse

08:59

Mouse but you can see as the game runs

09:02

we are capturing a trace just like we

09:04

did in the editor but now it is just my

09:07

game running it is not any of the editor

09:11

because we launched in Standalone mode

09:13

so that is pretty

09:15

cool when we close the game we will see

09:18

the trace stop now let's look at a real

09:21

world example I've been prototyping a

09:23

game with time rewinding mechanics the

09:26

way this works is each actor has a

09:28

component it keeps track of its

09:30

transforms and other state over time

09:33

when I rewind time I simply play that

09:35

state back in Reverse if you're

09:37

interested in the full details I have a

09:39

whole video on it but that's the gist of

09:41

what's going on I also built a debug

09:43

visualization feature that allows me to

09:45

see all of that state unfortunately when

09:48

I turn it on and a bunch of state has

09:50

accured my frame rate absolutely tanks

09:52

I'm really abusing the debug drawing API

09:56

when I was looking at fixing this issue

09:58

I was actually really surprised about

10:00

why it's slow so it's a great example of

10:02

why profiling is important to figure out

10:05

what's going on I started by

10:07

instrumenting my code I added bookmarks

10:10

which again gives that little text

10:12

visualization in the timeline view of

10:14

unreal insights and by adding CPU

10:17

profiler Scopes which will show up on my

10:19

flame graph so I've got a bookmark for

10:21

every time I turn my Snapshot

10:24

visualization on and off which is that

10:27

debug feature and I've also got a

10:29

bookmark whenever I begin or end a

10:32

rewind I've also gone through and

10:34

instrumented all of the individual

10:36

functions in my component so I can

10:38

confirm that I understand why things are

10:40

slow I was expecting the slowest part to

10:43

be in debug draw snapshots because what

10:45

we're doing is we're going through all

10:46

of that state that we've captured we're

10:48

calling draw debug point over and over

10:50

and over every frame and draw debug line

10:53

connecting all of those points over and

10:55

over every frame here is what the

10:57

profile actually looks like exactly as

11:00

we expected the moment we turn on the

11:02

debug visualization our frame rate tanks

11:05

the density of the work that's happening

11:06

in our flame graph goes way down and on

11:09

our frame timings we can see that we go

11:12

from running around 200 frames per

11:15

second dropping all the way down to 10

11:18

frames per second if I select one of

11:21

these frames and press F we can drill in

11:23

and see what's going on the total time

11:26

on the game thread is about 110

11:29

milliseconds interestingly most of that

11:32

time is spent here in game thread weight

11:35

for tasks about 90 milliseconds of that

11:37

110 milliseconds the rest of the time is

11:40

being spent ticking our rewind

11:43

components and calling debug draw

11:45

snapshots which is what we expected to

11:47

be slow some of these calls are up to 2

11:50

milliseconds for a single actor this

11:51

would be completely unacceptable in a

11:54

real game but the 14 milliseconds we

11:57

spent ticking does not explain why is

12:00

the frame 110 milliseconds long my

12:03

original intuition was I'm going to come

12:05

in to debug draw snapshots I'm going to

12:08

you know Kick the Can down the road a

12:10

little bit not really optimize this very

12:12

hard use the lifetime properties on

12:15

those apis to to make less calls every

12:18

frame but this is a pretty good hint

12:21

that that's not going to work and the

12:23

reason that's not going to work is the

12:24

way debug draw point and debug draw line

12:27

actually work is they write down some

12:29

State and that state actually gets

12:32

consumed as part of rendering work and

12:35

in fact if we scroll down and look at

12:38

other fra other threads we can see that

12:40

background worker number 14 in this case

12:43

is where all that work is happening 94

12:45

milliseconds of that 1110 millisecond

12:48

frame is happening on a background

12:49

thread if I shift to the compact View

12:52

and zoom out a little bit what we will

12:54

see is there are these big blocks of

12:57

work happening on very ious background

12:59

threads and that's because the renderer

13:02

is doing a bunch of background work that

13:03

is moving around every single frame but

13:06

this is really what the bottleneck is

13:08

that is causing uh our frame rate to dip

13:11

so hard

13:12

unfortunately the details of what we are

13:15

doing there is not

13:17

instrumented my next step was to go into

13:19

the engine source code add some

13:21

instrumentation rebuild from Source

13:23

repoint my project on top of that and

13:25

this is probably overkill for the common

13:27

case but I really wanted to cons confirm

13:30

that I understood what was going on here

13:32

here's what a similar profile looks like

13:34

with that instrumentation added we can

13:36

see that all the time is spent in draw

13:38

debug Primitives and underneath that we

13:40

are calling some functions in F batched

13:43

elements uh so drawing points drawing

13:46

thick lines in the code if we just

13:48

scroll through there's a RDG event for

13:53

adding debug Primitives that then calls

13:57

into the element back Patcher uh there

14:00

is a whole bunch of logic that is

14:02

running here in F batched elements draw

14:05

and this is where all of the actual work

14:07

for debug drawing is happening so our

14:10

current approach is totally doomed I had

14:13

to do something completely different

14:15

visualization V2 Grand reveal note we're

14:18

running at a locked 120 frames per

14:20

second when I turn the visualization on

14:23

WE remain at a locked 120 frames per

14:26

second the way I solved this performance

14:29

problem is I moved off of the debug

14:31

drawing pipeline entirely I made a new

14:33

rewind visualization component that

14:35

derives from the instanced static mesh

14:38

component there's only one function here

14:40

that is really important it's set

14:42

instances from snapshots and I

14:44

refactored my debug draw snapshots

14:46

function on the rewind component to

14:49

Simply turn around and call set

14:51

instances from snapshot on the

14:52

visualization component the way set

14:55

instances from snapshots works is

14:57

instead of running through all of of the

14:59

state snapshots and directly calling

15:02

debug drawing functions it instead runs

15:04

through those snapshots samples them

15:07

pulls out a bunch of transforms based on

15:10

how much time has passed and how much

15:12

movement has occurred since the last

15:15

snapshot it then does a little bit of

15:18

math to adjust the rotation of those

15:21

transforms so that they look at one

15:23

another it then updates all of the

15:25

instance transforms on that instance

15:27

static mesh component parent at this

15:30

point all we're doing is using the

15:32

standard unreal mesh drawing pipeline

15:35

which is very good at drawing a lot of

15:37

meshes and for the mesh I just used

15:40

unreal's modeling tools to take a Taurus

15:43

and an arrow and uh make a very super

15:47

dumb simple mesh kind of looks like a

15:49

Sonic ring but it makes me happy here's

15:51

what the profile looks like with the new

15:54

solution the main thing to notice is

15:55

that our frame rate remains completely

15:58

lock locked at 120 FPS we don't have a

16:01

big degradation even when we turn on the

16:04

timeline visualization you can see

16:05

that's happening CU our bookmark is

16:07

still here if I pick an arbitrary frame

16:09

and drill in what we're going to see is

16:12

that one that frame time is way way down

16:16

uh total frame time now is on the order

16:18

of about 9 milliseconds versus the 100

16:20

milliseconds that we saw before and the

16:23

time we spent ticking also went way down

16:26

previously we were ticking for about 13

16:27

milliseconds

16:29

and some of our biggest offenders in the

16:32

rewind component were taking 2

16:33

milliseconds each to tick now they're

16:36

running between about 10 and 20 micros

16:39

seconds on a fat one most of this is

16:42

still in visualized timelines if I

16:44

wanted to have an absolute ton of actors

16:47

there are some pretty obvious things I

16:48

could do to improve this further but for

16:51

now our total time ticking for the

16:53

entire frame for All actors in my world

16:55

is less than a millisecond we have

16:57

plenty of frame budget left and we are

17:00

no longer spending 50 to 100

17:03

milliseconds on that debug draw

17:05

Primitives RDG pass so this is solved as

17:10

usual all my code will be up on GitHub

17:12

feel free to do whatever you want with

17:13

it that's all for today's Whirlwind tour

17:15

of unreal insights if you found this

17:17

useful you'd be doing me a solid by

17:19

doing the standard YouTube engagement

17:22

shenanigan slam that like button ring

17:24

that Bell and if you want to learn more

17:26

about my rewind project definitely check

17:28

out that video until next time be kind

17:30

to one another

17:38

Peace