♪ [MUSIC] ♪ [NARRATOR] Welcome to Unite Now where we bring Unity to you,
wherever you are. [ANDREW] Hello, everyone,
and welcome to today's session on optimization in Unity. Today's session
is going to be an introduction to the optimization strategy
in how to optimize a game in Unity. Without further ado,
we are going to go ahead and dive in. This voice that's speaking to you,
I'm Andy Jevsevar. I'm the Director of Technology
at KairosXR where we specialize in XR
for training use cases. But I'm also joined today
by another team of instructors who help me put on this session. James is here, Kamran is here,
Alejandro is here, Nicolas, as well as Daniel. There is a full team here
helping run this session, make sure that all your questions get
answered and to provide that support. Go ahead and say hello
to the team. They will be helping
manage the chat and all of your questions that you may ask. With that said, if you do
have a question, we really encourage you to use
the Q&A webinar panel. That is the best place for us to
track and answer those questions. I do want to remind you
that the goal of this session is to get all those
questions answered. As your questions come up,
feel free to drop them in the Q&A tab there in the Zoom,
and we'll be able to address those. If you are joining us
for the first time, we do recommend this Zoom layout
in order to be able to follow along and track the chat and the Q&A. This is an ideal Zoom layout. One last note here,
if you have a comment, anything letting us know,
we're doing in front or anything that's not necessarily a question,
feel free to go ahead and drop that in the chat. Again, reserve the questions
for the Q&A and anything else
can go in the chat. As I just mentioned,
we have the difference between the Q&A panel
and the comments. It's always important
to be respectful, and courteous there, constructive. These sessions
are designed to actually dive in and get your hands dirty
on a project learn these topics
by actually moving through the techniques and the
various features in Unity. With that said, we are going
to be using Unity 2019.3. I encourage you to have a Unity
2019.3 Project open and ready. You can find the Assets
at this link. We've also gone ahead
and dropped a link in the chat. If you have not already
downloaded the Assets, please do so. We will have that again in the chat
if you follow that link there. Then as you may already know,
the session's going to be recorded. What this means is that
you will be able to watch this back. If you want to see something again, you'll be able to review this
session on the Unity Learn page. This also means
that all other sessions that we've run are recorded and there for your access as well. Again, if this is your first time,
as I just mentioned, you can catch up on the recordings
on the Unity Learn site. We are going to be using a Unity Project, so
I encourage you to download that. We'll have a moment here to make sure that everyone
has it downloaded and set up. I do encourage you to follow along, so
you can get the most out of these. Again, if you have questions,
feel free to drop those. We want to be able to address
all of your questions during the session and anything
that doesn't quite fall under the question category,
thoughts and comments, please reserve those for chat. What are we going to do today?
We have an hour. We are going to talk about
optimization in Unity. That entails some
optimization strategy. What are the techniques
you should be following to optimize a game.
Then we're going to jump into a few challenges. We'll look
at improving scripting performance; improving the batching
and draw call performance; then also configuring
Occlusion Culling. One thing I want to draw
your eyes to on this page here is on the right side, we have
the Watch, Do, and the Explore. When you see the stop sign,
that's going to mean that I'm going to be going through a demo. When the stop sign
is on the screen, I recommend that you just watch,
watch the demo. All these demos will be followed
by a green thumbs-up. That means it's your time to shine. You can dive into Unity,
attempt the challenge, ask questions, we'll be
there to help answer them. And then we will have a couple
explore opportunities as well where you can continue
to explore the topic and as always, continue
to ask those questions. What are we hoping
to get out of this session? We are, again, using this session
as an introduction to optimization in Unity. We will optimize
the script performance of this game that we've included. We will improve
the batching performance. We'll also configure
Occlusion Culling. With that said, we do want
to make sure that everyone has the Project
downloaded on their machine and are able to follow along.
We are going to take a moment here and make sure everyone has the Unity
Project set up on their machine. Step one for setting
the Project up, you will want to go ahead and go to
the Unity Learn site, and download the Asset Package. We dropped this link in the chat. You can refresh that
in the chat as well. But step one here, you need
to download the Asset Package. I'm going to leave this up
for a minute, and let you guys download
that Asset Package. When you've gone ahead and downloaded
that package, or it's downloading, just give us
the thumbs up in the chat. Let us know that you're good to go
and we'll move on to the next step. If you have any questions,
feel free to drop those in the Q&A. We got a question
right off the bat here about which template to use. We'll see that in the next step,
but we'll be using the Standard 3D Template. Again, if you've not
downloaded these yet, James just posted the link
again there in the chat. You can click on that,
but it looks like a lot of folks are good to go, so we're going to
move on to the next step. Once you've downloaded the Assets,
go ahead and open up a new Project in Unity. Again, it's important
that you use Unity 2019.3. That's where we've tested the
projects, we know it works there. This is the Unity version we'll be
using for all the Learn Lives. Using Unity 2019.3,
the sub-version, whatever's after .3
is not as important. But make sure you are in 2019.3. Go ahead and select 3D template,
and create that project. Let us know in the chat
when you've created that project, and we'll move on
to the third step. Some folks are getting that set up. Getting the green light here,
let's continue on. Once you've created the Project,
you downloaded the Assets, let's marry the two. What you want to do
is in the Project, you want to drag and drop
that Unity Asset Package into the Project, and go ahead
and import everything in. Getting the green light here
from a lot of folks. Again, if you missed a step,
lean on that Q&A, we could support you there,
but we are going to continue on. We want to dive in, and again, today we're
talking about optimization. What's important about optimization
is to understand some basics about what performance is
and how it impacts our Unity Projects. We will do just a couple of minutes
of overview of what performance is and what optimization is,
what it even means and then we'll dive
into the Project. We're going to start
with performance. What is performance in Unity?
You may have heard this thrown around, and maybe you have
some understanding of it, maybe it's really solidified,
maybe it's not. But I do want to make sure
that we're all starting from a baseline level
of understanding here. We know that Unity
is able to render your application in real-time. That is the value of Unity,
that's why it's so amazing. You can do everything in real-time.
We can make our changes, we can see those
impacted immediately. How does it do this? The fact that it's real-time
means that... all these calculations
are happening every second. And more specifically,
60 to 90 times every second, depending on the game,
or your experience. That means that 60
to 90 times every second, the whole game loop
here is executed. That means that all
the initialization's happening, the physics, the animation,
receiving the player input, running through all
of your scripts, your game logic, and then rendering
everything out to the Scene. Now, that's pretty fascinating
when you think about that. That's a lot of items
that are happening in literally a split second,
60 to 90 times every second. When we talk about performance,
we're talking about this process and how long it takes
to do this process. How can you check
the performance in Unity? We just learned what goes in to
every single frame that is rendered, and we know that we
are trying to render 60 to 90 frames every second. But how can we check this performance? There's two areas
that we need to understand. We have the CPU
and we have the GPU. The CPU definitely does the majority
of the work for most projects. The CPU with all the preparation. The preparation work
includes grouping all the similar objects together
and sending those off to be rendered onto the screen. It includes the physics, the game
logic, as well as the input. The counterpart is the GPU. This is responsible
for all the graphics. This does all the processing,
the rendering, the shaders, and the lighting. These two work in tandem
to render your Scene, render every frame. Again, how can we monitor
this performance in Unity? There are a few metrics
that you'll see come up over and over again, it's important
to have a baseline understanding. We've got frames per second,
batches, and tris or tri count. Let's start with frames per second. The frames per second
is the number of frames that are rendered every second. As I mentioned, this is typically
between 60 and 90 frames per second depending
on your experience. This literally means how many times
that game loop is executed every single second. If you have a really optimized Scene,
you can get that number way up. You can do that 100 times
per second even. If one of those pieces
in that game loop is taking a long time,
performance can suffer, and that's when the frames
per second can be reduced. What this will end up in as you
can see in this GIF right here, it will end up in a glitchy
game experience. Want to make sure that majority
of Unity experiences should be targeting around
60 frames per second to be safe. If you are doing VR, it's important
to bring that up to 90, depending on the headset
that you're using. But 60 is a pretty safe number
to be targeting for the most part. There is this handy formula here. If you are familiar
with frames per second already, you've done some
optimization in the past, and added this formula here,
so you can figure out the time it takes per frame by
dividing your target FPS by 1,000. 1,000 divided by your target FPS
will give you the time per frame
in milliseconds. So that's helpful, you're really
getting into the nitty-gritty. But if this is your first time,
working into optimization, don't worry so much
about this formula, you can reference that later on. The next item here
that you will hear us talk about and we'll be covering today
is the idea of batches. What is a batch? A batch is the number of draw calls
that we can send off to be drawn to your
screen each time. A quick aside, a draw call is... it's the set of instructions that
tells Unity how to draw an object, literally render it
onto your screen. Right here on the screen right now,
we have these three cubes. They could each be
a separate draw call. We could send the... first cube off, we can send
the second cube off, we could send third cube off.
Each of these is a draw call, meaning that it is a set of
instructions how to draw that cube. It will define where its position
is, what its size is, all that. You have three draw calls.
The number of batches is how we group
those draw calls together. Just like... a batch of cookies. This is a batch of draw calls. Batching these draw calls
together allows us to streamline the performance, and save work on the GPU side. A quick analogy to help solidify your understanding of batches
and why they're important. There is the idea
that if you go to a grocery store, and you are sent to get
milk, chicken, and eggs, rather than doing one trip
to the store to get the milk, and then going home, then going
to do another trip to the store to get the eggs, and then a third
trip to get the chicken, you could combine that all into one
trip and batch that together. It's a similar concept, we don't
need to be sending these draw calls off to the GPU individually, we can group
them together and send them off. And we'll see how that works
more in Unity during this session. The last number
that you'll hear about and will come up during
performance optimization is tris, or tri count. This is the number
of mesh triangles. As you can see in this example, this is pulled from the
Unity documentation. We have two of the same model,
but one of the models has a lot more tris or triangles. And that is the number of vertices
that are included in that model. As the tri count goes up,
you are going to get higher resolution meshes
and more detailed objects, but at the cost of performance. Something that has
a lower tri count will be able to render faster
in your Scene. How can we check
this performance in Unity? We talked about what goes
into each frame, some of the key metrics
that we can view, difference between
the CPU and the GPU. And now, we'll tie it
back to Unity. When we're in our Unity project,
how do we view this? And how do we view
the current performance and start to optimize the project? There's three main windows that
you'll use during optimization. Starting the left, we have
the Stats window, and this is a quick preview of how
your experience is performing. As you can see here, you can see some
of these things we talked about. We can see how long
it takes per frame. We can see the FPS
or frames per second, right here, 7.4 in this screenshot. You can see the number of batches. This is the number
of batches being sent off to be drawn to your screen. And you can also see the tris. There are a few other metrics
that as you dive deeper, you'll be able to look into more. But again, the stats,
the high-level view, a quick snapshot, you can grab this
information right from the game view. And I'll show you that
in Unity in a second. When you want to dive in
and see what factors are leading in to your FPS, and your batches and your tris,
we're going to use the Profiler. The Profiler allows us
to dive deeper, see exactly what's contributing
to our performance. The last one, we won't spend
too much time on today, may get to it as an explore
opportunity, but we're going to focus
on the Profiler mostly today. The last one is a Frame Debugger.
And what the Frame Debugger allows you to do is to step through
your project frame by frame. You can break it down,
all of this, see what's happening, the first frame,
second frame, third frame. And this is helpful when you need
to optimize those batch counts and those draw calls
and things like that further. Again, today's session is going
to focus mainly on the Profiler. But did want to call out that
the Frame Debugger is another tool you have
at your disposal. We are almost there. This is the last slide,
then we will jump into Unity. But this is probably the most
important slide of the entire deck. If there's nothing else
to take away from today, please remember this. And that is there's a process
to optimization no matter what project
you're working on, what device you're targeting,
we need to follow this process. If you're not following
this process, you're throwing mud at the wall. In order to save yourself time,
and be really efficient, go ahead and follow this process. What we want to do
when we're noticing that there is a performance problem. We see that our frames
per second has dropped, or maybe we're experiencing some
laggy behavior in our gameplay. The first thing you're going to need to do
is benchmark the project. So, that means you'll gather the data,
and we'll talk about how to do this. We'll determine that the project
is CPU or GPU bound. That is something on the scripting
and physics and input side, or is it something
on the rendering side. You look at the results,
and then identify an issue. Want to tackle these issues
in order of priority. If we got a really big problem, we're
going to address that one first. But we need to identify.
We don't need to be guessing. There's no guesswork involved
with optimization. Once you've identified that, we
can figure out what the cause is, we can make the change,
and then we can repeat. Again, this is the most important
slide of the deck. I want to make sure
you're taking this to heart, and you will save yourself
lots of time as you are optimizing
the performance in your Unity experiences.
That was a lot of information but do want to make sure we're
starting with the base level of optimization understanding. Now that we have that, we are going
to jump into the first demo. But before I do, notice that there
is the stop sign on the top right. With that said, I'm going to recommend
that you just watch. I'll go through the demo, and then,
we'll turn it over to you, you'll have an opportunity to dive into
the project and work through it. Here I am in the Unity project. When you open a new project, you'll just be in a sample Scene. But once you've imported
that Asset Package, you will have a UnityEduTeam
project folder. You can open this up, and
if you go to the _Scenes folder there is a Scene called the Maze. That is what we're going to be working in today. We go ahead and open this up. What are we looking at here?
This is a Maze game. As you can see, I can scroll out,
take a look at it. It's a pretty standard maze. And I just go into Play mode here,
we can test it out. Again, there's optimization
we need to do, but if I just click around,
my character will go to where my mouse has clicked. And we're able
to navigate around. That's what we're looking at,
we're looking at this game. As you can see, it may be hard
through the screenshare, but there is
definitely some lag going on. The FPS is not as high
as it should be for this game, especially when I'm running
on a computer. Let's go ahead and discuss
some of our strategies to optimize this. Think to yourself what is
the first step you would take here. If you have a project, you know that there
is performance issues, we can start to see it, we can just feel
it from looking at the project. These things are glitchy,
a little bit laggy. How would we go about fixing this? Remember that we need to start with
a baseline benchmark level of data that we can then compare against. As I mentioned, there are
three windows we can use. The first one is the Stats. As I said, the Stats window's
included in the Game view, and it's right here. You can click
on the Stats and this will open up. As I move around, we can get the
Stats in real-time, this is pretty cool. We can get a lot of information
right out of the Stats window, and this gives us a great benchmark. You can see that the FPS
is relatively low here. We're down to about 20.
Our batch count, you can see where that is.
Tri count, things like that. It's important to continue
to move through the experience. You don't want to just look at the
Stats in one specific place. You would want to continue
to move the character around to get a better feel
for the entire experience. But this give us a good idea
of where our FPS is, and the fact that we need
to bring this number up. Again, the Stats
is a quick preview. But now, if we want to dive and actually identify some issues. The Stats window is only going
to help us so much. What is the next step?
Where do we go now to figure out how to optimize
this experience? Let me close the Stats window. The next window that I talked
about, where we're going to be spending most of the time today
is called the Profiler window. I can find this by doing
Window, drop down, going down to Analysis,
and opening up the Profiler. This will open up this window here. Now, what I am going to do with this
is I'm actually going to dock it at the bottom, so we can look at the Profiler and
look at our game at the same time. I'll drag that Profiler window down
so we can see it here. Then continue to move around to
see how the Profiler updates. But let's go ahead
and break down this Profiler because it can be... there is a lot of information there and if it's your first time looking at it I do want to make sure that we
understand what we're looking at. I'm going to click somewhere. Let's take a step back and talk about what the Profiler is
and what we're looking at. The Profiler is a break down
of the performance in our project. What this top part is showing us
is a graph, a visual view of how long each of the components
in our game loop is taking. As you can see here, the CPU alone
is responsible for the rendering, the scripts, physics, et cetera. And we can see that information
in a visual way here. What we can do is we can actually move
through frame by frame. We can say each frame,
see how the performance changes. You can see as we click
the next frame, this bar right here
is moving across, and that is literally going
through frame by frame, you can see how the performance
changes in each of those frames. This top view of the Profiler,
I'm just going to expand this actually so we can see
a little bit more information. Its just a graph of the performance data. In this top half of the Profiler,
there's a lot of other information that we
don't need to focus on right away, but we can start to dive into as we
become better with optimization. We can look at something
like physics, we can see how the physics
performance is being affected. If you're doing a 2D game,
see the physics for 2D. There's all sorts
of information here. But for today's session,
and for the majority of the optimization work
that you'll be doing, we can focus on the CPU,
then we can focus on the rendering. That's two areas
that we can focus on today. You can actually turn off
the other ones if you want. If they're in your way,
you can click them. What this is doing is it's taking
them away. Right here, we have physics, and we don't want
to look at that right now, I could deselect that
and that will go away. Again, we can leave them on,
doesn't matter. What we're going to be focusing on
is the CPU and the rendering. We have this graphical view on top. We know we can step through
frame by frame of our experience. We can view this data
in this visual format here. Then that brings us
to the bottom half of the Profiler. And now this is the meat
and potatoes of the Profiler. You may be seeing
a different view by default. You may be seeing
the Timeline view. If you select where it says Timeline,
you can switch to Hierarchy. There is also the Raw Hierarchy which provides a level
of detail more on the breakdown
of what's going on in your Scene. Right now, we are going to focus
on the Hierarchy. Make sure you have
the Hierarchy View selected. What we'd like to do
is we'd like to figure out why our Scene is taking
so long to render. This is really cool,
because we can select anywhere on here,
select the frame to look at, and we can go through
into our Hierarchy, we can start to crack these areas
open, and we can dive in and see exactly what's going on and exactly
how long this stuff is taking. I just popped open
the PlayerLoop, for example, and we can see that the PlayerLoop
is taking 42 milliseconds. That is a pretty long time. We want to bring this number down. The overall time
that a frame should take is under 20 milliseconds.
We're looking for that. A short time per frame,
we need a lot of frames per second. As I break this open, I can look
at what is taking the most time, we can address those problems. With the PlayerLoop, I can see that the first thing
that we have going on is some sort of Update and ScriptRunBehaviourUpdate. This operation is taking
21.78 milliseconds. That is a significant chunk
of the time that is taking our game to process each frame. You may ask how do we know
how long it's taking in total. Depending on your machine,
you can actually see right here how long
it's taking in total. Some GPUs are limited, they're not
going to get that number. If you see that number, then
you can just add the two together. Sometimes, it's limited
like this machine I'm working on,
an older MacBook Pro. I don't have the GPU data,
but I can see the CPU is taking 52.71 milliseconds. Each frame it's taking that long. 21 of those 52 milliseconds,
is spent on this update. A significant portion of time. Before we dive down
and see exactly what's going on, we can see what proportion
of time this is if we go to the Timeline view. We're looking
at the Hierarchy view. I can select this, go back
to Timeline view. Again, this is a visual
representation of what is happening each frame. What are we looking at here? We can see that on our main thread,
we start at zero milliseconds. Again, every frame
is taking from zero all the way up to about 53. We can see that this
is the information that's happening in every frame.
These are the PlayerLoop, we have a bit of an EditorLoop,
which will be the Editor update, and then we'll finish off with some
more PlayerLoop. As you move down vertically, you're getting more
detailed information. In that PlayerLoop,
specifically we're spending a giant chunk of our time
on this ScriptRunBehaviourUpdate. Then you can see the second half
of our time is spent on rendering. Right away, we can see our issue
will be in this chunk right here. Because this is the majority of
this entire 53 millisecond frame. Spending over half of it
on this PlayerLoop. And of the PlayerLoop, we are
spending a majority of that time on this ScriptRunBehaviourUpdate. We have identified that we have
a problem with our CPU. We've identified
that it is in the PlayerLoop, and it has something to do
with this ScriptRunBehaviourUpdate. Looking at the Profiler, in just
a few seconds, or a few minutes looking at this, we've already
determined what the issue is. Let's dive in and figure out
what is causing that issue. We looked at the Timeline view, we've seen that this
is the majority of the time. We've identified that the
Update.ScriptRunBehaviourUpdate here is taking a significant chunk. How do we figure out
what is causing this? Let's go back
to the Hierarchy view. What we can do, it's really cool,
is we can continue to pop this open, and we can dive in and see
exactly what's going on. It's on some BehaviourUpdate. We know that it is some
Assembly somewhere, SimpleAI.Update,
that may be important. We can continue to dive in here. We can see under
the time milliseconds here, that this SimpleAI.Update method
is taking 21.63 milliseconds. We continue to dive down. We see that LogStringToConsole
is taking a bunch of time. We continue
to dive into this, there's some information that's happening
every time we Log something. What have we identified so far? We know that this is sorted by
the length of time that it takes. We know that a Log somewhere
in the SimpleAI.Update is causing a huge chunk
of our time to be wasted here. Let's figure out what is going on. SimpleAI.Update, let's see
if we can find that in the project. What I'm going to do now,
is go out of Play mode. I will look at the project here. There's a few options.
You know there's a Log. We can look at the console
and see if there's a Log. Looks like there's a Log message
that is happening a lot. I could double-click on this.
That will take me to the issue. We also know it's happening
in the SimpleAI.Update. If I go to the project,
I could look at the Scripts, and I could find
the SimpleAI script. We know something in here
is causing a huge hit to the performance. I'm going to go ahead
and open this script up. I want to make sure you are seeing
Visual Studio now and not just Unity.
You should see Visual Studio. Now that you are seeing the script, what we are going to do is we know that SimpleAI.Update
is where the problem is. Now, we can just move through.
You didn't write this code. So, we are just going to do some investigation. We know the Update
is causing the issue. We look at the Update, we could
track what's happening here. It looks like CheckState
method is called, I could scroll up, find CheckState. CheckState method is called,
FindVisibleTargets is in there. That is called, so let's find that. Again, we're looking
for a Log message that may be happening pretty frequently,
causing an issue. We can see that there is
a Log message here that maybe was added
during development to let the developer know
that the player was found. This is something that's happening
every single frame. Who knows how many SimpleAI
instances there are in the game. This is happening way too much. To me, looking at this now,
it doesn't look like we need this. This isn't crucial to anything
in our experience. I could comment it out,
we could test that. I just comment that out. I'm going to go back to Unity
and share my screen. Back into Unity, and now
that I've commented that out... I could go ahead and play
the project again and look at the Profiler
and see the updates. I will not do that right now,
because I've been talking at you for a few minutes, and I would like
you guys to give it a shot. What I'm going to do is I'll jump
back to the slides, I'll turn it over to you
for the first challenge. What I would like you to do is follow that process
that I just demoed. Where we open up
the Profiler, play the game, we drop down, we identify what's taking up
the majority of the time. Once we've identified that,
we can make an update, and then we want to evaluate
how that update affected our project and our
performance. We have the green thumbs up in the right,
that means it's your turn to go. Go ahead and follow through
with that update that I made, follow that process
in your project. Make that update and see
if you can notice an improvement in performance. Let us know in the chat
when you've got that set up. And we will continue on. Again, if you have any questions,
feel free to drop those in the Q&A, and we'll
address those there. If you were able to accomplish
that relatively quickly, go ahead and take it
a step further. We looked at analyzing that script, and seeing what's taking
a lot of time in there. There was that Log message
which takes a lot of time. But there is some physics updates
that could be made as well. If you already have that Log
message fixed, go and dive in, I challenge you to optimize
some of those physics calls. There is a way to optimize
the physics in there. Go ahead and check that out. Again, as you have any questions,
post those in the Q&A and we'll address those there. A really great question, and maybe
I zoomed over it a little quickly. We have a question here about
how did I decide it was CPU
versus GPU bound. Great question, glad you asked
for clarification there. The way we figured that out
is we actually looked at the Profiler. We looked at the Timeline view, and we saw that the CPU was doing the majority
of the work in the frame. We could see the entire
frame is happening. We see that the CPU
was not waiting at any moment. There is a call that will come up, it's called WaitForGFX
or WaitForGPU. When we see that call, we know
that the GPU is taking longer
and the CPU is waiting. In this case, we didn't see
that the CPU was waiting. We'll see that once
we fix this issue, we'll see that there is some time
where the CPU is waiting for the GPU to finish. That's when we know that we're
moving in to a GPU issue. To boil that down, how do you know
if it's CPU or GPU bound? In the Profiler, it will say how
long it is taking for the CPU, and depending on your graphics card
or your machine, it will actually just tell you right there,
how long it's taking the GPU as well . You can compare the two values,
whichever is taking longer, is the one that has the problem,
the one you want to fix. If your machine is like mine, you can't see
the GPU data explicitly, then what you want to do
is you want to look at the Timeline view
in the Profiler. And you want to see
if there's anywhere where it says, WaitForGFX or WaitForGPU in it.
The CPU is waiting, that is waiting for the GPU,
which means a GPU issue. If it's now waiting,
then we know it's a CPU issue. Great question. A comment in the chat here. If you see the WaitForGFX command it can mean that the CPU is... waiting to get information
out to the GPU. You are going to want to make sure the CPU
is optimized in that case. The GPU is waiting for anything
from the main thread. Then you are going to be CPU bound. The main thread is CPU, and the CPU needs
to complete that main thread before it sends off to the GPU. A great message there in the chat. Generally finding GameObjects,
or calling any find type method, in an Update loop is not ideal. It's a great catch, there. Update that, cache those results. Note I was using Visual Studio. You can use MonoDevelop or Rider or any other
code Editor that you have. Also worth noting that you
will want to check multiple frames to find the themes, what continues
to happen, continues to come up. Something that's just happening
in a single frame, maybe it's not the core issue. Got to look for those themes,
repeating patterns. In this case, that Log message is
one that will continue to come up if you scan through
multiple frames. Great questions. We'll continue
to get those answered. We are going to continue on, a couple
more challenges we want to get to. Really appreciate the engagement, and are getting all
the questions answered. With that said, let's go ahead
and continue on. We are going to focus on the next challenge. I'm going to jump back into Unity here. Again, you have
that stop sign, top right. I'm going to encourage
that you just watch and do the next demo.
This one should be a bit faster, and it'll get you back
into the challenge. I'm going to come back into my project. If you remember, I commented out
that line of code that was causing the Log message. What I'm going to do now is I'm going to go ahead
and go to Play mode, and we should see that ScriptRunBehaviour that was taking a long time before, is taking around 22 milliseconds. We should see, if I jump forward
to one of these newer frames, we should see that the issue
is less of an issue. Good question about obtaining
a 15 to 20 FPS average with 15 milliseconds of rendering. Right there, you can see the math,
that the math works out. If it's 50 milliseconds. We know there's
1,000 milliseconds in every second. 20 times 50,
brings that up to 1,000. That does add up right there. Great question. The Editor loop
is all of the updates that need to happen to make sure
that the Unity Editor continues to run smoothly. Things like updating
the Hierarchy, updating the Inspector,
your Project View console, all of that stuff
is part of the Editor loop. With that said, it's important
that you're testing your experience on your target platform. You're profiling
on your target platform. You can profile
on any target platform, which is a really cool feature Unity has. If you're building a mobile game,
for Android, let's say, you can deploy to the Android, then you can remote profile
from the Android. That's what you'd want to do,
you want to profile from your target device, so you're
getting the most accurate results. I think the Project here
just hit a snag and it would work itself out. But let me go ahead and just restart it. We don't want to sit here and wait. While I restart this,
I'm going to jump back, and I'm going to have you guys
get a head start on the challenge. What I would like you to do... is I would like you to run
through the Profiler again. Now that you have that fixed,
what is the next largest issue? One of the things
you'll see coming up, and it's still a CPU-side issue,
is the batching. It seems the rendering
is taking a long time. If you start to see rendering
taking a long time, that's usually because
there's too many batches. How do we update the batches?
There are a few things we can do. We can jump into Dynamic Batching
and set that up. Let's go ahead and do that. One of the biggest changes
you can make and it's really easy to make
is marking objects static. Objects that are not moving in
the Scene can be marked as static. Then you can check
the results in the Profiler. You can take it a step further
by baking that light. I'm going to go ahead and restart
my Project here. But go ahead and get a head start
on this challenge, and as for questions, feel free
to drop them in the Q&A. I see a few questions here. "Can't find Other
in Project Settings." You open the Project Settings,
that will open a new window. And on the left side, you will see
a few different options. What you want
to select there is Player. And then in the Player, there
should be an option for Other. Then in there, you'll be able to
find the Dynamic Batching. Turn that on, it's a check box. That's great because
it's free performance. Turn that on and you essentially
get free performance. You want to make sure that
is turned on in your experience. I think you are right. Project Settings,
and then Player, and then Other. Other is underneath Player.
Good catch there. My machine may need
to do a quick restart, but we are coming up to the end. I want to make sure we
do the last challenge, we can stick around
and answer some questions. The ways to increase batching,
go to Project Settings > Player, part of the Project Settings
then Other. You can enable Static Batching
and Dynamic Batching. Marking objects as static,
we can do this in the Inspector. Again, only do this for objects
that are stationary. But if they're stationary,
you can mark them static, that will get you a lot
of performance right away. Check those results. Then take it a step further, you can
bake the lighting for the Scene. We have the last step here, which is setting up
the Occlusion Culling. This takes it one step further, and pretty much says,
"Any objects that are not in the camera view
that are marked Static, we can ignore them when rendering." How do we set this up?
It's pretty straightforward. If you've marked
the objects as Static, then you can skip this first step. All you need to do is open up
the Occlusion window. It's under
Window > Rendering > Occlusion. Then you select Bake. Just one button. You turn that on and you can get
some more performance back again. There's this cool visualization
you can do in the Scene view. But what you can also do
is run the Scene with the Profiler
and see those results. Few additional questions. I'd like to make sure
to get those addressed. Is it Baked Global Illumination? We've got that one to be answered. How do you make the objects Static? In the Inspector, once you select
an object in the Hierarchy, in that Inspector, where you can
see the object's position, and all the components it has,
on the top right of the Inspector, there should be
a check box for static. You can mark that static,
it should right away. Marking something
as static in Unity just lets Unity know that it
doesn't need to expect that object's
going to move. If it's not going to move,
then it can batch it together with other objects around
or a few other things, physics that increase
the performance. Generally, marking objects
as static is a great way to improve performance
in your experience. The goal of today's session
was to talk about a strategy for... optimizing your experiences. You want to start the Profiler, and you would want
to end with the Profiler. It all starts and ends
with the Profiler. You look at the Profiler,
you identify where time is being eaten up in your
rendering and your game loop. Then once you've
identified that issue, then you go and change it,
and you see how that change
affects your experience. Do want to call out,
we have this session recorded. There is a session that we've ran
on the same topic, the same slides, the same project. I know a few of these challenges, we kind of hit a wall
with that game there crashing. Just needing to restart. But you can find this
on Unity Learn sites, so I encourage you
to check that out. In the last minute here, want to jump forward. Let you know you can
take this a step further. The best way to solidify the topic
is to do the challenge yourself. If you've done the project so far,
you've removed that debug line, you've set up the batches,
marking objects as static, doing light baking, there's still
a lot more you can do. You can take that SimpleAI script,
you can take that a step further. Remove unnecessary calls,
optimize things, again, using the Profiler to guide
the way that you're approaching them. When you have
a more peformant game, you can start to add
more features as well. I encourage you to continue
exploring here, and explore in your own projects
using the Profiler to... fix the performance issues
and optimize them. Once you have them optimized,
you can add more features. It's an exciting thing. With that, we have
the Learn Live Connect Group. We will drop a link
to that in the chat. That's a great place
to continue the conversation outside of these sessions. With that, we thank you
for joining. We're going to stick around
for a few minutes. Make sure to answer
these questions that are coming in. Feel free to stick around
and get those. But if you have to jump, again,
join us in the Connect Group, and if you'd like to connect,
you can find me here at bit.ly/AndyXR. We will see you in a future
Learn Live session. Thank you. ♪ [MUSIC] ♪