Death by a Thousand Ticks: Why Gameplay Systems Become Slow | Konrad Słoń | GameDev Day 2026
Read full transcript 45 segments
-
Conrad is with us. Conrad is with us. We invite him here, We invite him here, We invite him here, he will tell us about " he will tell us about " death by a thousand death by a thousand death by a thousand ticks." I'm interested ticks." I'm interested ticks." I'm interested to see all of this, because to see all of this, because to see all of this, because performance and performance and performance and gaming tools gaming tools are always critically are always critically are always critically important things. So, important things. So, important things. So, Conrad, it's Conrad, it's Conrad, it's your turn, we're interested your turn, we're interested your turn, we're interested to hear what you've to hear what you've to hear what you've prepared. prepared. So, well, let's So, well, let's get started. Hello everyone get started. Hello everyone get started. Hello everyone and welcome to and welcome to and welcome to my report. my report. Today I want Today I want to talk a little about to talk a little about to talk a little about optimization and optimization and how to work with it. how to work with it. The idea of my talk is The idea of my talk is that that gameplay performance problems rarely gameplay performance problems rarely arise because of one arise because of one arise because of one obviously difficult piece of obviously difficult piece of obviously difficult piece of code. Often code. Often code. Often when you're working with when you're working with when you're working with gameplay code, gameplay code, gameplay code, you have a lot of pieces you have a lot of pieces you have a lot of pieces that look that look that look perfectly acceptable. perfectly acceptable. They can be very They can be very cheap, but when there are a cheap, but when there are a cheap, but when there are a lot of them, you end up lot of them, you end up lot of them, you end up in a situation where you have a in a situation where you have a in a situation where you have a bunch of really bunch of really bunch of really heavy functions and you don't heavy functions and you don't heavy functions and you don't know how to know how to know how to fix it. This is what we fix it. This is what we fix it. This is what we want want want to explore today, and before we to explore today, and before we to explore today, and before we delve deeper, delve deeper, delve deeper, let me briefly let me briefly let me briefly introduce myself, because introduce myself, because introduce myself, because we don't have much time.
-
we don't have much time. So, my name is So, my name is Konrad, I'm a senior Konrad, I'm a senior Konrad, I'm a senior gameplay programmer, gameplay programmer, gameplay programmer, and I'm currently working on a and I'm currently working on a and I'm currently working on a team helping team helping team helping CD Projekt Red on their CD Projekt Red on their CD Projekt Red on their upcoming game. So upcoming game. So upcoming game. So gameplay systems gameplay systems are a big part of are a big part of are a big part of my daily work. my daily work. Therefore, architectural Therefore, architectural problems similar to problems similar to problems similar to those we will discuss those we will discuss those we will discuss today. I today. I today. I have to have to have to solve them solve them solve them all the time, so I am very all the time, so I am very all the time, so I am very happy to share happy to share happy to share my knowledge with you. my knowledge with you. So, to begin any optimization, we any optimization, we any optimization, we need to determine need to determine need to determine what exactly we are what exactly we are what exactly we are optimizing. There optimizing. There optimizing. There is no is no is no abstract abstract abstract performance budget in games. performance budget in games. performance budget in games. Ultimately, in Ultimately, in Ultimately, in game development we have what we game development we have what we game development we have what we call a "frame". And call a "frame". And call a "frame". And everything that has to happen is everything that has to happen is everything that has to happen is competing for time competing for time competing for time within this frame. within this frame. within this frame. So before we So before we So before we look at the look at the look at the gameplay example gameplay example gameplay example we're talking about today we're talking about today we're talking about today . Let's . Let's . Let's quickly define what a quickly define what a quickly define what a frame is and what frame is and what frame is and what this this this definition means from a definition means from a definition means from a productivity perspective, because it productivity perspective, because it productivity perspective, because it all depends on all depends on all depends on perspective.
-
perspective. The definition of a frame The definition of a frame can vary. can vary. So I want to lay a So I want to lay a solid foundation for solid foundation for solid foundation for the rest of my talk. the rest of my talk. So what So what exactly is a frame? How exactly is a frame? How exactly is a frame? How should we understand this during a should we understand this during a should we understand this during a presentation? At the presentation? At the presentation? At the simplest level, simplest level, simplest level, we can think of a we can think of a we can think of a frame as a snapshot of frame as a snapshot of frame as a snapshot of our game at a specific our game at a specific our game at a specific point in time. So, point in time. So, point in time. So, a frame will tell us where a frame will tell us where a frame will tell us where our our our objects are, what animation is objects are, what animation is objects are, what animation is currently playing, currently playing, currently playing, what is happening in the what is happening in the what is happening in the gameplay, what gameplay, what gameplay, what the interface looks like, the interface looks like, the interface looks like, where the where the where the camera is, what effects are camera is, what effects are camera is, what effects are visible, etc. All of these visible, etc. All of these visible, etc. All of these elements together elements together elements together form a state that form a state that form a state that ultimately becomes what ultimately becomes what ultimately becomes what we see on the we see on the we see on the screen during the game. And, screen during the game. And, screen during the game. And, of course, games are not of course, games are not of course, games are not static images. static images. static images. To create the illusion of To create the illusion of To create the illusion of continuous motion, continuous motion, continuous motion, we create these we create these we create these shots over and over again, shots over and over again, shots over and over again, and this brings us to an and this brings us to an and this brings us to an important aspect from a important aspect from a performance perspective. So performance perspective. So how much time do we have how much time do we have how much time do we have to create the to create the to create the next frame? After all, next frame? After all, next frame? After all, we need to do we need to do we need to do it quickly enough to it quickly enough to it quickly enough to get the same get the same get the same illusion of continuous illusion of continuous illusion of continuous motion. So this is motion. So this is motion. So this is extremely important to extremely important to extremely important to know. And regarding the staff, know. And regarding the staff, know. And regarding the staff, there are things that we have to, I there are things that we have to, I there are things that we have to, I think, define to think, define to think, define to understand this.
-
understand this. Usually, when we Usually, when we talk about talk about talk about gaming performance, gaming performance, gaming performance, we're talking about FPS. This is what we're talking about FPS. This is what we're talking about FPS. This is what the players see. the players see. When you see When you see discussions on discussions on discussions on the internet or elsewhere, the internet or elsewhere, the internet or elsewhere, you'll notice that "oh, this you'll notice that "oh, this you'll notice that "oh, this game couldn't reach game couldn't reach game couldn't reach such and such an amount of FPS such and such an amount of FPS ." That's why it's bad, ." That's why it's bad, ." That's why it's bad, or good, or or good, or or good, or something else. From our something else. From our something else. From our perspective as developers, perspective as developers, perspective as developers, we call this we call this we call this frame time. But frame time. But frame time. But when I'm programming a game when I'm programming a game when I'm programming a game and working with code, and working with code, and working with code, frame time is often a frame time is often a frame time is often a much more useful much more useful much more useful way of thinking about way of thinking about way of thinking about solving a problem. solving a problem. Because Because frame rate, or FPS, frame rate, or FPS, frame rate, or FPS, tells us how tells us how tells us how often we create a often we create a often we create a frame. And frame time, frame. And frame time, frame. And frame time, on the other hand, tells us on the other hand, tells us how long it how long it how long it actually takes to actually takes to actually takes to create that create that create that frame. So these are not frame. So these are not frame. So these are not exactly two independent exactly two independent exactly two independent terms. Rather, they terms. Rather, they terms. Rather, they describe the same describe the same describe the same thing, but from different thing, but from different thing, but from different angles. So, when we angles. So, when we angles. So, when we want to describe want to describe want to describe how much time we have to how much time we have to how much time we have to run a game at a certain run a game at a certain run a game at a certain frequency, we know frequency, we know frequency, we know how much time we have how much time we have how much time we have to render each to render each to render each frame. So if you frame. So if you frame. So if you want to have a game with want to have a game with want to have a game with around 30 FPS, you have around 30 FPS, you have around 30 FPS, you have around 33 milliseconds of around 33 milliseconds of around 33 milliseconds of time. If you have 60 FPS, time. If you have 60 FPS, time. If you have 60 FPS, you only have about 16
-
you only have about 16 you only have about 16 milliseconds, and so milliseconds, and so milliseconds, and so on. So, depending on. So, depending on. So, depending on what frequency on what frequency on what frequency you need, you you need, you you need, you should execute should execute should execute your code faster. And for your code faster. And for your code faster. And for this presentation, this presentation, this presentation, let's assume let's assume let's assume that our goal is 60 FPS. So that our goal is 60 FPS. So to achieve this in to achieve this in to achieve this in every frame, that is, to every frame, that is, to every frame, that is, to have a continuous have a continuous have a continuous video sequence, we have video sequence, we have video sequence, we have about 16 about 16 about 16 milliseconds to milliseconds to milliseconds to create one create one create one frame. Of course, 16.67 is a frame. Of course, 16.67 is a frame. Of course, 16.67 is a more accurate number. And more accurate number. And more accurate number. And here is an important nuance: here is an important nuance: here is an important nuance: when we say that at when we say that at when we say that at 60 FPS we have 16 60 FPS we have 16 60 FPS we have 16 milliseconds, as milliseconds, as milliseconds, as programmers and programmers and programmers and game developers we do not game developers we do not game developers we do not get all this get all this get all this time to create a time to create a time to create a frame, because a frame is the frame, because a frame is the frame, because a frame is the product of the work of the entire product of the work of the entire product of the work of the entire game. So we have game. So we have game. So we have work work work done on the CPU, done on the CPU, done on the CPU, work done on the GPU, and work done on the GPU, and work done on the GPU, and they all have their own they all have their own they all have their own limitations and limitations and limitations and dependencies. Even dependencies. Even dependencies. Even if you look only at the if you look only at the if you look only at the CPU side, which is CPU side, which is CPU side, which is more important from my point of view, more important from my point of view, more important from my point of view, it is only one participant in the it is only one participant in the it is only one participant in the entire process.
-
entire process. Physics takes time, Physics takes time, animation takes animation takes animation takes time, the engine takes time, the engine takes time, the engine takes time, plus audio, time, plus audio, time, plus audio, networking, and a bunch of other networking, and a bunch of other networking, and a bunch of other resources. And all of this is resources. And all of this is resources. And all of this is competing for the competing for the competing for the same time and limited same time and limited same time and limited resources. So these 16 resources. So these 16 resources. So these 16 milliseconds are milliseconds are milliseconds are a limit for the entire a limit for the entire a limit for the entire game, not a budget for game, not a budget for game, not a budget for gameplay. Gameplay gameplay. Gameplay is only part of the whole is only part of the whole is only part of the whole . . . So in a real So in a real So in a real project, we project, we project, we only get a fraction of this only get a fraction of this only get a fraction of this time, and that fraction time, and that fraction time, and that fraction is not even constant. We is not even constant. We is not even constant. We need to actively need to actively need to actively manage this, and sometimes manage this, and sometimes manage this, and sometimes that time will be longer that time will be longer that time will be longer and sometimes shorter. And, and sometimes shorter. And, and sometimes shorter. And, of course, the overall of course, the overall of course, the overall execution model here execution model here execution model here is simplified. We won't is simplified. We won't is simplified. We won't talk about talk about talk about CPU and GPU pipelines or CPU and GPU pipelines or CPU and GPU pipelines or anything like that because it would be anything like that because it would be anything like that because it would be too too too complicated for this complicated for this complicated for this conversation, and it's not conversation, and it's not conversation, and it's not important to important to important to understand what understand what understand what we want to achieve. we want to achieve. So, I want you to So, I want you to understand: gameplay understand: gameplay is just one is just one is just one factor that factor that factor that affects affects affects frame time, along with all the frame time, along with all the frame time, along with all the others. This is the others. This is the others. This is the view I want us to view I want us to view I want us to take, because as take, because as take, because as programmers it's programmers it's programmers it's important for us to know that we important for us to know that we important for us to know that we don't own the entire don't own the entire don't own the entire frame. And since frame. And since frame. And since we only own a we only own a we only own a part of it, we part of it, we part of it, we need to think about the need to think about the need to think about the bigger picture.
-
bigger picture. For example, our code For example, our code might execute in might execute in might execute in 4 milliseconds or 4 milliseconds or 4 milliseconds or so, and we so, and we so, and we might think, might think, might think, okay, that's not much, okay, that's not much, okay, that's not much, because we have 16, and that's because we have 16, and that's because we have 16, and that's only four. But from only four. But from only four. But from our perspective, these our perspective, these our perspective, these four might be four might be four might be very close to the very close to the very close to the limit we have limit we have limit we have for our for our for our gameplay code. gameplay code. So, when we add So, when we add new game elements, new game elements, new game elements, we have to think about we have to think about we have to think about the speed of this the speed of this the speed of this feature, because sometimes, as we feature, because sometimes, as we feature, because sometimes, as we add more add more add more challenges, these small challenges, these small challenges, these small pieces pieces pieces accumulate, and accumulate, and accumulate, and even if the number even if the number even if the number looks small, on looks small, on looks small, on the scale of the project the scale of the project the scale of the project it can become it can become it can become large. So we large. So we large. So we need to ask how need to ask how need to ask how our code behaves our code behaves our code behaves when the entire game when the entire game when the entire game scales and scales and scales and more more more animations, animations, animations, interfaces, or interfaces, or interfaces, or other other other resource-intensive systems appear. resource-intensive systems appear. And we have to And we have to fit into all these fit into all these fit into all these constraints. This is constraints. This is constraints. This is where where where the title of this report comes from, the title of this report comes from, the title of this report comes from, because performance problems are because performance problems are actually quite actually quite nice when they nice when they nice when they look like the look like the look like the first example.
-
first example. first example. Because we Because we Because we open open open the profiler, find the profiler, find the profiler, find the function and see: the function and see: the function and see: okay, it takes 4 okay, it takes 4 okay, it takes 4 milliseconds. It's easy milliseconds. It's easy milliseconds. It's easy to spot, and I know: to spot, and I know: to spot, and I know: okay, I need to okay, I need to okay, I need to go inside this go inside this go inside this feature and fix feature and fix feature and fix it, and everyone will be it, and everyone will be it, and everyone will be happy because we happy because we happy because we improved the functionality improved the functionality , and that's cool. But , and that's cool. But , and that's cool. But gaming gaming gaming performance performance performance usually doesn't decrease like that usually doesn't decrease like that usually doesn't decrease like that . Instead, . Instead, . Instead, we get many we get many we get many separate, perfectly separate, perfectly separate, perfectly acceptable pieces of acceptable pieces of acceptable pieces of work. You can work. You can work. You can put a put a put a function inside function inside function inside other functions and other functions and other functions and say, "Okay, this is say, "Okay, this is say, "Okay, this is cheap." "This is just cheap." "This is just cheap." "This is just one check." "This is one check." "This is one check." "This is just one challenge." And just one challenge." And just one challenge." And when I test it, when I test it, when I test it, it works very, very it works very, very it works very, very fast. So none of fast. So none of fast. So none of them seem them seem them seem particularly scary particularly scary particularly scary when considered in when considered in when considered in isolation. But when isolation. But when isolation. But when you do this you do this you do this work every frame, work every frame, work every frame, and we have dozens or and we have dozens or and we have dozens or hundreds of objects hundreds of objects hundreds of objects doing this. So how do doing this. So how do doing this. So how do we identify the problem? we identify the problem? we identify the problem? Eventually, all these Eventually, all these Eventually, all these little bits and pieces little bits and pieces little bits and pieces start to eat up a start to eat up a start to eat up a significant portion of significant portion of significant portion of our gaming our gaming our gaming budget. And this is a budget. And this is a budget. And this is a real problem.
-
real problem. real problem. Big features are easy to Big features are easy to Big features are easy to find and fix, find and fix, find and fix, but it's the small but it's the small but it's the small decisions along the way that decisions along the way that decisions along the way that prove much prove much prove much harder to harder to harder to find and find and find and fix in fix in fix in later stages. So later stages. So , if we look at the , if we look at the performance problem this performance problem this way, we get way, we get way, we get three categories of three categories of three categories of optimization. These are optimization. These are optimization. These are cost, frequency and cost, frequency and cost, frequency and scale. And suddenly, scale. And suddenly, scale. And suddenly, according to this according to this according to this definition, we have definition, we have definition, we have three levels, and we three levels, and we three levels, and we need to adjust need to adjust need to adjust them to get the them to get the them to get the optimal code. If optimal code. If optimal code. If we want to make we want to make we want to make an operation cheaper, we an operation cheaper, we an operation cheaper, we use a use a use a cost level, cost level, cost level, of course. If we of course. If we of course. If we do something less often, that's do something less often, that's frequency. Or we frequency. Or we frequency. Or we can reduce can reduce can reduce the number of objects the number of objects the number of objects that cause something, and that cause something, and that cause something, and that would be scale. And that would be scale. And that would be scale. And when we multiply when we multiply when we multiply all of this together, we get the all of this together, we get the all of this together, we get the frame time frame time frame time we need to execute we need to execute we need to execute our code. And the our code. And the our code. And the important thing is that they important thing is that they important thing is that they are not mutually exclusive, are not mutually exclusive, are not mutually exclusive, right? So, in a real right? So, in a real right? So, in a real system, when you system, when you system, when you optimize something, you optimize something, you optimize something, you have to think about have to think about have to think about it holistically. And it holistically. And it holistically. And sometimes you will sometimes you will sometimes you will optimize, optimize, optimize, for example, cost and for example, cost and for example, cost and frequency at the same time.
-
frequency at the same time. frequency at the same time. That is, you don't That is, you don't That is, you don't optimize it optimize it optimize it in isolation, one by in isolation, one by in isolation, one by one. The first level is one. The first level is one. The first level is probably probably probably the most obvious, the most obvious, the most obvious, the most popular, and the the most popular, and the the most popular, and the first thing that comes to first thing that comes to first thing that comes to mind when it comes mind when it comes mind when it comes to optimization. So to optimization. So , you have a certain , you have a certain , you have a certain operation, it takes operation, it takes operation, it takes time. So our instinct time. So our instinct time. So our instinct is, "Okay, is, "Okay, is, "Okay, let's look let's look let's look inside this inside this inside this function and try to function and try to function and try to optimize it." And what optimize it." And what optimize it." And what can we do here can we do here ? We can ? We can ? We can use use use better algorithms, better algorithms, better algorithms, avoid avoid avoid memory allocation, memory allocation, memory allocation, cache something, or cache something, or cache something, or speed up the loop. And speed up the loop. And speed up the loop. And sometimes that's exactly what you sometimes that's exactly what you sometimes that's exactly what you need to do. But need to do. But need to do. But there's a danger here, because by there's a danger here, because by there's a danger here, because by optimizing cost optimizing cost , you're already assuming , you're already assuming , you're already assuming that the work itself has to that the work itself has to that the work itself has to be done, because be done, because be done, because if you're trying if you're trying if you're trying to speed up a quick to speed up a quick to speed up a quick operation, you're saying, " operation, you're saying, " Okay, I need Okay, I need Okay, I need this operation." "I can't this operation." "I can't this operation." "I can't remove it." " remove it." " So I have to do it So I have to do it So I have to do it faster." And that's the faster." And that's the faster." And that's the decision you decision you decision you make there. So, make there. So, make there. So, before optimizing the before optimizing the before optimizing the way way way something is done, I want to something is done, I want to something is done, I want to question question question the assumption that it the assumption that it the assumption that it should be done at all should be done at all should be done at all . That's the . That's the . That's the point. So for point. So for point. So for most of this most of this most of this talk, we won't talk, we won't talk, we won't talk about talk about talk about cost. We will cost. We will cost. We will talk about frequency talk about frequency talk about frequency and scale. The frequency and scale. The frequency and scale. The frequency will tell us how often will tell us how often will tell us how often this work should be done in general this work should be done in general this work should be done in general . And . And . And the scale is how many the scale is how many the scale is how many objects actually have to objects actually have to objects actually have to do this work.
-
do this work. And this is interesting because And this is interesting because none of these approaches none of these approaches none of these approaches require us require us require us to speed up the to speed up the to speed up the operation itself. If something operation itself. If something operation itself. If something costs 1 µs or costs 1 µs or costs 1 µs or even less, it is even less, it is even less, it is still worth 1 µs. still worth 1 µs. But doing this 10 But doing this 10 times instead of 60, or times instead of 60, or times instead of 60, or for 10 agents instead of for 10 agents instead of for 10 agents instead of 100, dramatically 100, dramatically 100, dramatically changes the frame time contribution changes the frame time contribution changes the frame time contribution , and that's exactly what we , and that's exactly what we , and that's exactly what we want to achieve with want to achieve with want to achieve with these changes. And these changes. And these changes. And these two dimensions are very these two dimensions are very these two dimensions are very often defined by often defined by often defined by our our our gameplay architecture. Where gameplay architecture. Where gameplay architecture. Where we need to we need to we need to decide where decide where decide where to put the work, who to put the work, who to put the work, who does it, and what does it, and what does it, and what actually actually actually triggers it. So, triggers it. So, triggers it. So, instead of instead of instead of starting with starting with starting with micro-optimizations at the micro-optimizations at the micro-optimizations at the feature level, we feature level, we feature level, we will gradually will gradually will gradually change how our change how our change how our game system game system game system plans work, and plans work, and plans work, and thanks to this thanks to this thanks to this we can buy we can buy we can buy some time. At this some time. At this some time. At this point, I think we point, I think we point, I think we can move on to can move on to can move on to abbreviations, and our abbreviations, and our abbreviations, and our first goal will be what first goal will be what first goal will be what we call we call we call frequency. We've frequency. We've frequency. We've mentioned this mentioned this mentioned this before. So, for before. So, for before. So, for game game game logic programmers, there is a very logic programmers, there is a very logic programmers, there is a very obvious place where obvious place where obvious place where frequency can frequency can frequency can imperceptibly get out of imperceptibly get out of imperceptibly get out of control. This function control. This function control. This function is called tick. And is called tick. And is called tick. And if you work in Unity if you work in Unity , then for you, , then for you, , then for you, for example, it will be update.
-
for example, it will be update. for example, it will be update. So, this is a function that So, this is a function that So, this is a function that is called every is called every is called every frame. The tick itself frame. The tick itself frame. The tick itself is not a problem, as is not a problem, as is not a problem, as it is an extremely it is an extremely it is an extremely useful mechanism, and useful mechanism, and useful mechanism, and you are unlikely to want to you are unlikely to want to you are unlikely to want to completely completely completely abandon it. The trap abandon it. The trap abandon it. The trap is that is that is that placing something in a placing something in a placing something in a tick implicitly tick implicitly tick implicitly answers a very answers a very answers a very important question. important question. important question. Namely: how often should I Namely: how often should I Namely: how often should I run this piece of run this piece of run this piece of code? And the answer code? And the answer code? And the answer will be: every frame. will be: every frame. So you need to So you need to decide if it's really decide if it's really decide if it's really worth calling something worth calling something worth calling something every frame, because it every frame, because it every frame, because it will cost you time will cost you time will cost you time every time, as the every time, as the every time, as the name suggests. Let's name suggests. Let's name suggests. Let's see what see what see what happens when we happens when we happens when we take a perfectly take a perfectly take a perfectly reasonable piece of reasonable piece of reasonable piece of game logic and game logic and get the following get the following response by default. So, we response by default. So, we response by default. So, we want to call everything want to call everything want to call everything every frame, and every frame, and every frame, and we'll see how that we'll see how that we'll see how that works. To do works. To do works. To do this, in the rest of this, in the rest of this, in the rest of the talk we will the talk we will the talk we will use a very use a very use a very sophisticated game sophisticated game sophisticated game example. I spent example. I spent example. I spent some time some time some time programming, but there programming, but there programming, but there will only be screens.
-
will only be screens. It's very simple. I'll It's very simple. I'll explain to you how explain to you how explain to you how this game works so that you this game works so that you this game works so that you can later understand how can later understand how can later understand how we change everything. So, we change everything. So, we change everything. So, we have this kind of we have this kind of we have this kind of shooter. Your player is shooter. Your player is shooter. Your player is here, on this line, and you here, on this line, and you here, on this line, and you can move can move can move along it from left along it from left along it from left to right. You can, of course, to right. You can, of course, to right. You can, of course, shoot at shoot at shoot at enemies, and you enemies, and you enemies, and you need to stop them need to stop them need to stop them before they before they before they get to you. get to you. get to you. So, we have enemies So, we have enemies So, we have enemies on the other side. And these on the other side. And these on the other side. And these enemies move in enemies move in enemies move in lines. And the important thing is that lines. And the important thing is that lines. And the important thing is that they move they move they move as if in a queue. So as if in a queue. So as if in a queue. So the enemy can't just the enemy can't just the enemy can't just change the line. If change the line. If change the line. If the enemy appears on the the enemy appears on the the enemy appears on the first line, he first line, he first line, he will move to the will move to the will move to the end of it. So, end of it. So, end of it. So, line by line. line by line. line by line. Enemies appear at Enemies appear at Enemies appear at the beginning of the segment and the beginning of the segment and the beginning of the segment and move towards the move towards the move towards the player. And if the enemy player. And if the enemy player. And if the enemy gets to the end of gets to the end of gets to the end of that line, that's bad for us that line, that's bad for us that line, that's bad for us , because it means , because it means , because it means we couldn't we couldn't we couldn't defend our base defend our base defend our base or something. And that's the or something. And that's the or something. And that's the end of the game for us, end of the game for us, end of the game for us, so that's not what so that's not what so that's not what we want we want we want to achieve at all. Along the line to achieve at all. Along the line to achieve at all. Along the line I drew there, I drew there, I drew there, enemies start enemies start enemies start shooting at you, but shooting at you, but shooting at you, but they can't they can't they can't shoot randomly. They shoot randomly. They shoot randomly. They need to aim, need to aim, need to aim, so they start so they start so they start checking to see if checking to see if checking to see if the player is the player is the player is in line of sight. And, of course, in line of sight. And, of course, in line of sight. And, of course, they have a they have a they have a certain cone of vision for this.
-
certain cone of vision for this. certain cone of vision for this. So, if the player is in So, if the player is in So, if the player is in sight, they sight, they sight, they start shooting at start shooting at start shooting at him. That's the whole him. That's the whole him. That's the whole gameplay. It's gameplay. It's gameplay. It's really simple. really simple. really simple. Let's quickly Let's quickly Let's quickly summarize to summarize to summarize to understand what we understand what we understand what we need to implement need to implement need to implement for enemy behavior. for enemy behavior. for enemy behavior. So, for each So, for each So, for each enemy, we need to enemy, we need to enemy, we need to move it towards the player move it towards the player . We need . We need . We need to track to track to track the distance to the player. the distance to the player. the distance to the player. We need to We need to We need to update the update the enemy's gameplay state. That is, things enemy's gameplay state. That is, things like: is he still like: is he still like: is he still alive? Or other states. alive? Or other states. alive? Or other states. And finally, we And finally, we And finally, we need to need to need to track progress track progress track progress along the way so we know along the way so we know along the way so we know when it reaches the when it reaches the when it reaches the end. There is nothing end. There is nothing end. There is nothing particularly complicated particularly complicated particularly complicated here. These are here. These are here. These are small, completely small, completely small, completely logical parts of the logical parts of the logical parts of the game mechanics. game mechanics. Let's move on to what a Let's move on to what a "tick" looks like in "tick" looks like in "tick" looks like in this case. Each this case. Each this case. Each enemy is an actor, a enemy is an actor, a enemy is an actor, a regular object regular object regular object that can be that can be that can be placed on a level. placed on a level. Each enemy has Each enemy has its own update, or its own update, or its own update, or "tick," or whatever we'll "tick," or whatever we'll "tick," or whatever we'll call it. During call it. During call it. During each "escape" we each "escape" we each "escape" we move the enemy move the enemy move the enemy forward. Then we forward. Then we forward. Then we calculate calculate calculate the distance to the player and the distance to the player and the distance to the player and check if the check if the check if the enemy can attack, enemy can attack, enemy can attack, start targeting, start targeting, start targeting, or check if the or check if the or check if the player is within player is within player is within range or in line of range or in line of range or in line of sight. Then we sight. Then we sight. Then we update its status, update its status, update its status, check its check its check its health level, update health level, update health level, update the interface, and possibly the interface, and possibly the interface, and possibly destroy the enemy if its destroy the enemy if its destroy the enemy if its health is low health is low . After that, we
-
. After that, we . After that, we update the progress of the update the progress of the update the progress of the path. path. path. But that doesn't mean But that doesn't mean But that doesn't mean we're moving it at this point we're moving it at this point we're moving it at this point . We're . We're . We're just checking: " just checking: " How close are you How close are you How close are you to the end of the road?" And we to the end of the road?" And we to the end of the road?" And we want to display want to display want to display this progress somewhere in the this progress somewhere in the this progress somewhere in the interface, for interface, for interface, for example. So we example. So we example. So we can say: " can say: " The enemies have gone 75% of The enemies have gone 75% of the way, and if you the way, and if you the way, and if you want to destroy them quickly want to destroy them quickly want to destroy them quickly , you will , you will , you will do it." So, this do it." So, this do it." So, this needs to be updated needs to be updated needs to be updated quite often. It's not something quite often. It's not something we can do at we can do at we can do at the end of it all. And the end of it all. And the end of it all. And all this looks all this looks all this looks quite acceptable. quite acceptable. quite acceptable. None of this None of this None of this looks too looks too looks too scary. But by adding scary. But by adding scary. But by adding all four of these all four of these all four of these operations, we made operations, we made operations, we made one architectural one architectural one architectural decision with almost no decision with almost no decision with almost no discussion. discussion. So, each enemy So, each enemy does all of their does all of their does all of their work every frame. work every frame. work every frame. And the question might be, And the question might be, And the question might be, "Okay, they "Okay, they "Okay, they do it, but is it do it, but is it do it, but is it expensive?" Maybe it's expensive?" Maybe it's expensive?" Maybe it's cheap, so maybe cheap, so maybe cheap, so maybe we don't we don't we don't need to need to need to optimize it at all. And optimize it at all. And optimize it at all. And the answer is that the answer is that the answer is that we don't know whether we don't know whether we don't know whether it's expensive or not. So it's expensive or not. So it's expensive or not. So this is exactly the point this is exactly the point this is exactly the point where we need to where we need to where we need to just open just open just open the profiler and the profiler and the profiler and see if see if see if it's expensive. And when we it's expensive. And when we it's expensive. And when we capture that in Unreal capture that in Unreal capture that in Unreal Insights, for example, and Insights, for example, and Insights, for example, and look at one look at one look at one enemy, it's cheap. We enemy, it's cheap. We enemy, it's cheap. We don't need to don't need to don't need to do anything there because it's only do anything there because it's only do anything there because it's only about 84 about 84 about 84 microseconds for microseconds for microseconds for this sample. And if I this sample. And if I this sample. And if I saw something like that saw something like that saw something like that in a profiler, it in a profiler, it in a profiler, it probably wouldn't cause probably wouldn't cause probably wouldn't cause me immediate me immediate me immediate concern. And this is
-
concern. And this is concern. And this is precisely the problem that precisely the problem that interests us today. Because when we interests us today. Because when we profile, it's very profile, it's very profile, it's very tempting to look tempting to look tempting to look at a big expensive at a big expensive at a big expensive block or a big block or a big block or a big expensive function that expensive function that expensive function that takes a few takes a few takes a few milliseconds. And this is not milliseconds. And this is not milliseconds. And this is not such a function. So, such a function. So, such a function. So, the cost of execution is the cost of execution is the cost of execution is not particularly interesting not particularly interesting . Of course, you can . Of course, you can . Of course, you can try to try to try to optimize it, but I do optimize it, but I do optimize it, but I do n't know if n't know if n't know if you'll get the benefit you're hoping for you'll get the benefit you're hoping for you'll get the benefit you're hoping for , because , because , because cost is only cost is only cost is only one part of the one part of the one part of the equation. But we equation. But we equation. But we can look at can look at can look at other parts of it. other parts of it. other parts of it. So, one execution is So, one execution is So, one execution is cheap. We have a frame cheap. We have a frame cheap. We have a frame rate for each rate for each rate for each frame, but we're not frame, but we're not frame, but we're not building a game with one building a game with one building a game with one enemy. So, enemy. So, enemy. So, let's go back to let's go back to let's go back to our equation. And our equation. And our equation. And the cost has not the cost has not the cost has not changed. Each changed. Each changed. Each individual tick is still individual tick is still individual tick is still cheap. But now cheap. But now cheap. But now we have scale. And every we have scale. And every we have scale. And every enemy we enemy we enemy we add brings with it add brings with it add brings with it another copy of the another copy of the another copy of the same cheap same cheap same cheap work. And 10 enemies work. And 10 enemies work. And 10 enemies mean 10 executions.
-
mean 10 executions. mean 10 executions. 100 enemies means 100 enemies means 100 enemies means 100 executions. And suddenly 100 executions. And suddenly 100 executions. And suddenly something that seemed something that seemed something that seemed completely unimportant completely unimportant completely unimportant when checking a single when checking a single when checking a single enemy instance enemy instance enemy instance can become very can become very can become very significant at the significant at the significant at the frame level. So when we frame level. So when we frame level. So when we look at the entire look at the entire look at the entire population. Scale doesn't population. Scale doesn't population. Scale doesn't make an individual make an individual make an individual operation expensive, but operation expensive, but operation expensive, but when you aggregate when you aggregate when you aggregate each of those operations each of those operations each of those operations across many actors, across many actors, across many actors, it can become expensive it can become expensive it can become expensive and problematic for and problematic for and problematic for you. And this is what you. And this is what you. And this is what happens when we happens when we happens when we stop looking stop looking stop looking at one enemy and at one enemy and at one enemy and look at the whole group of look at the whole group of look at the whole group of enemies. So, nothing has enemies. So, nothing has enemies. So, nothing has become more expensive. This is still the same become more expensive. This is still the same cheap tick we cheap tick we measured. We just measured. We just measured. We just did it 50 times did it 50 times did it 50 times in one shot. Now these in one shot. Now these in one shot. Now these small tasks are small tasks are small tasks are piling up, and we piling up, and we piling up, and we have about 4.2 have about 4.2 have about 4.2 milliseconds. Which doesn't milliseconds. Which doesn't milliseconds. Which doesn't look too look too look too bad, but bad, but bad, but remember what we remember what we remember what we said earlier: you have said earlier: you have said earlier: you have 16 milliseconds, but that's 16 milliseconds, but that's 16 milliseconds, but that's not your not your not your gaming budget.
-
gaming budget. Only a Only a fraction of these 16 fraction of these 16 fraction of these 16 milliseconds is allocated to gameplay. So milliseconds is allocated to gameplay. So milliseconds is allocated to gameplay. So spending over 4 spending over 4 spending over 4 milliseconds on a milliseconds on a milliseconds on a fairly simple fairly simple fairly simple enemy system enemy system enemy system suddenly becomes very suddenly becomes very suddenly becomes very substantial. This substantial. This substantial. This doesn't scale doesn't scale doesn't scale well. So well. So well. So instead of asking how to instead of asking how to instead of asking how to make it run make it run make it run faster, let's faster, let's faster, let's look at what exactly look at what exactly look at what exactly we're doing during we're doing during we're doing during this update. this update. this update. We have four elements of We have four elements of We have four elements of game logic. This is game logic. This is game logic. This is the position, distance to the position, distance to the position, distance to the player, status and the player, status and the player, status and flight progress. flight progress. flight progress. Now we have made one Now we have made one Now we have made one very strong very strong very strong assumption about assumption about assumption about each of them. Namely: each of them. Namely: each of them. Namely: they need they need they need to be called every frame. to be called every frame. to be called every frame. But do they really But do they really But do they really need this need this need this frequency of calls? frequency of calls? frequency of calls? Probably not. Let's Probably not. Let's Probably not. Let's look at these two at the very look at these two at the very look at these two at the very beginning. beginning. First we have a First we have a position update and position update and position update and our enemies are constantly our enemies are constantly our enemies are constantly moving towards the player. moving towards the player. So, could we So, could we update the traffic less frequently, update the traffic less frequently, update the traffic less frequently, for example? Of course, we for example? Of course, we for example? Of course, we can do this, can do this, can do this, but immediately there is but immediately there is but immediately there is the problem of the problem of the problem of interpolation and interpolation and interpolation and noticeable flaws in the movement.
-
noticeable flaws in the movement. This is not very good from a This is not very good from a player's point of view. So, player's point of view. So, player's point of view. So, for this example, for this example, for this example, let's say, "Okay, our let's say, "Okay, our let's say, "Okay, our game requirement is game requirement is to update this to update this to update this as often as possible." as often as possible." So, the position So, the position needs to be updated needs to be updated needs to be updated every frame. We can't every frame. We can't every frame. We can't change that. Let's change that. Let's change that. Let's look for other places look for other places look for other places where we can win where we can win where we can win some resources. Next some resources. Next some resources. Next comes what we comes what we comes what we call the call the call the player distance update, and player distance update, and player distance update, and this determines whether the this determines whether the this determines whether the player is in the player is in the player is in the attack zone, whether they are in attack zone, whether they are in attack zone, whether they are in line of sight, and so on. line of sight, and so on. Here my gameplay requirement is different, because different, because the question arises: "Do the question arises: "Do the question arises: "Do I really need to know I really need to know I really need to know the distance between the enemy the distance between the enemy the distance between the enemy and the player every and the player every and the player every frame, or is the player frame, or is the player frame, or is the player in the attack zone every frame?" in the attack zone every frame?" Probably not, because if Probably not, because if the check the check the check happens every happens every happens every few frames, or few frames, or few frames, or every 50-100 milliseconds, every 50-100 milliseconds, every 50-100 milliseconds, the player probably the player probably the player probably won't notice it because won't notice it because won't notice it because the attack isn't instantaneous.
-
the attack isn't instantaneous. It will be delayed It will be delayed due to reloading or due to reloading or due to reloading or other elements. other elements. other elements. The player does not know exactly when the The player does not know exactly when the enemy's next attack will be. So enemy's next attack will be. So if you if you if you delay this delay this delay this calculation a little, calculation a little, calculation a little, nothing nothing nothing will change for the player. And so, should will change for the player. And so, should will change for the player. And so, should this be called this be called this be called every frame? Probably not. every frame? Probably not. every frame? Probably not. So, these two functions So, these two functions So, these two functions are in the same are in the same are in the same update cycle, but update cycle, but update cycle, but that doesn't mean they that doesn't mean they that doesn't mean they should have the should have the should have the same same same call frequency requirements. And that's what call frequency requirements. And that's what call frequency requirements. And that's what we we we want to want to want to focus on now. So, focus on now. So, focus on now. So, let's take updating let's take updating let's take updating the distance to the player as the the distance to the player as the the distance to the player as the first example of first example of first example of optimization. The position is still optimization. The position is still optimization. The position is still updated every updated every updated every frame because we frame because we frame because we want smooth motion. want smooth motion. want smooth motion. But let's assume that But let's assume that But let's assume that checking the distance checking the distance checking the distance doesn't require such doesn't require such doesn't require such precision. So instead of precision. So instead of precision. So instead of executing it on the first, executing it on the first, executing it on the first, second, third, second, third, second, third, fourth frame, and fourth frame, and fourth frame, and so on, we can so on, we can so on, we can execute it execute it execute it periodically. The first, periodically. The first, periodically. The first, second, and third second, and third second, and third frames are just the frames are just the frames are just the enemy's movement, and in the enemy's movement, and in the enemy's movement, and in the fourth frame we not fourth frame we not fourth frame we not only move it, only move it, only move it, but also check if but also check if but also check if it can attack it can attack it can attack the player. We did not the player. We did not the player. We did not optimize the distance optimize the distance optimize the distance update function itself update function itself update function itself .
-
. . It costs the same amount of It costs the same amount of It costs the same amount of resources each resources each resources each time it time it time it is executed. We did is executed. We did is executed. We did n't change anything, we n't change anything, we n't change anything, we just stopped just stopped just stopped wasting this resource wasting this resource wasting this resource in every frame. in every frame. Of course, the four frames Of course, the four frames here are just for here are just for here are just for example. In a real example. In a real example. In a real system, you have to system, you have to system, you have to define this define this define this interval yourself, maybe it interval yourself, maybe it interval yourself, maybe it should be every second should be every second should be every second or third frame, or third frame, or third frame, maybe every 100 maybe every 100 maybe every 100 milliseconds or every other milliseconds or every other milliseconds or every other time. The important question is time. The important question is time. The important question is not how often you not how often you not how often you will call will call will call the function, but how the function, but how the function, but how often you should not often you should not often you should not do it. That is, do it. That is, do it. That is, how many moments in the how many moments in the how many moments in the frame execution time frame execution time frame execution time can you skip can you skip can you skip this call and this call and this call and save time. So, save time. So, save time. So, we reduce the frequency. we reduce the frequency. we reduce the frequency. Instead of calculating Instead of calculating Instead of calculating the distance eight times, the distance eight times, the distance eight times, we do it twice. We we do it twice. We we do it twice. We solved the problem, did solved the problem, did solved the problem, did n't we? We n't we? We n't we? We solved it, but solved it, but solved it, but now we've created another now we've created another now we've created another problem, because problem, because problem, because let's see let's see let's see what happens what happens what happens every fourth every fourth every fourth frame. Every enemy frame. Every enemy frame. Every enemy follows the same follows the same follows the same schedule. If schedule. If schedule. If you have 50 enemies, they you have 50 enemies, they you have 50 enemies, they skip the skip the skip the distance calculation for distance calculation for distance calculation for three frames, and then all three frames, and then all three frames, and then all 50 do it 50 do it 50 do it together on the fourth.
-
together on the fourth. We reduced the We reduced the overall amount of overall amount of overall amount of work, but work, but work, but concentrated it in concentrated it in concentrated it in one frame. one frame. Remember, our Remember, our limit is not the limit is not the limit is not the average average average CPU load. It is important CPU load. It is important CPU load. It is important whether whether whether individual staff members are investing in their individual staff members are investing in their individual staff members are investing in their time budget. If time budget. If time budget. If you have three easy shots you have three easy shots you have three easy shots and one expensive one, you're and one expensive one, you're and one expensive one, you're still going over still going over still going over budget and it's budget and it's budget and it's going to cause a rush, you going to cause a rush, you going to cause a rush, you can't do that. From the can't do that. From the can't do that. From the player's point of view, this player's point of view, this player's point of view, this will be noticeable even will be noticeable even will be noticeable even if the average FPS is, if the average FPS is, if the average FPS is, for example, 60, because a for example, 60, because a crash will occur every few frames. And crash will occur every few frames. And maybe on average maybe on average maybe on average everything is fine, but at the everything is fine, but at the everything is fine, but at the level of individual personnel, level of individual personnel, level of individual personnel, something is wrong, and we something is wrong, and we something is wrong, and we need to do something about it need to do something about it need to do something about it . And that . And that . And that brings us to brings us to brings us to another very important another very important another very important part of part of part of performance, which is performance, which is performance, which is called "frame called "frame pacing." So, when pacing." So, when pacing." So, when we talk about we talk about we talk about performance, it's very performance, it's very performance, it's very easy to focus easy to focus easy to focus on average FPS, on average FPS, on average FPS, average average average frame time, or cost, frame time, or cost, frame time, or cost, but we have to remember but we have to remember but we have to remember that the player doesn't that the player doesn't that the player doesn't experience the average experience the average experience the average frame. He feels frame. He feels frame. He feels the sequence of the sequence of the sequence of individual frames. So, individual frames. So, individual frames. So, here our work here our work here our work is distributed, as in the is distributed, as in the is distributed, as in the example above, example above, example above, relatively evenly.
-
relatively evenly. Therefore, each frame Therefore, each frame takes approximately the takes approximately the takes approximately the same amount of same amount of same amount of time. And this gives us a time. And this gives us a time. And this gives us a stable supply of stable supply of stable supply of personnel. And in the example personnel. And in the example personnel. And in the example below, you do below, you do below, you do about the about the about the same amount of work, same amount of work, same amount of work, but the distribution is different, and but the distribution is different, and but the distribution is different, and sometimes one frame sometimes one frame sometimes one frame lasts longer. lasts longer. Most of the frames are Most of the frames are cheap, but suddenly the cheap, but suddenly the cheap, but suddenly the fourth and eighth fourth and eighth fourth and eighth frames become significantly frames become significantly frames become significantly more expensive. And that's exactly what more expensive. And that's exactly what more expensive. And that's exactly what we got by we got by we got by forcing all of our forcing all of our forcing all of our enemies to perform a enemies to perform a enemies to perform a range check range check range check every fourth every fourth every fourth frame. So reducing frame. So reducing frame. So reducing average costs does not average costs does not average costs does not automatically result in automatically result in automatically result in good frame good frame pacing. If pacing. If pacing. If too much work too much work too much work is crammed into a single is crammed into a single is crammed into a single frame, we can frame, we can frame, we can go over our go over our go over our time budget and cause time budget and cause time budget and cause noticeable "jerks" noticeable "jerks" noticeable "jerks" even if the even if the even if the averages look averages look averages look perfectly fine. perfectly fine. perfectly fine. So, when we So, when we So, when we optimize frequency, optimize frequency, optimize frequency, there are two questions that there are two questions that there are two questions that need to be answered. need to be answered. need to be answered. First: how often First: how often First: how often should this work should this work should this work be done? And second be done? And second : how is this work : how is this work : how is this work distributed within the framework of the distributed within the framework of the distributed within the framework of the framework? So we have a framework? So we have a framework? So we have a third term to third term to third term to discuss. We have discuss. We have discuss. We have frame time, frame time, frame time, frame rate, and now frame rate, and now frame rate, and now frame pacing. And frame pacing. And frame pacing. And all three of these things all three of these things all three of these things need to be thought about during need to be thought about during need to be thought about during development. How to development. How to development. How to fix it then?
-
fix it then? fix it then? Instead of Instead of Instead of letting all letting all letting all enemies "wake up" enemies "wake up" enemies "wake up" on the same on the same on the same fourth fourth fourth frame, we can frame, we can frame, we can distribute them among distribute them among distribute them among other frames that are other frames that are other frames that are not busy. not busy. Let's take 100 Let's take 100 enemies, because it enemies, because it enemies, because it will be easier will be easier will be easier to show in this example. Movement still to show in this example. Movement still to show in this example. Movement still happens happens happens for everyone in every for everyone in every for everyone in every frame. We can't frame. We can't frame. We can't change that. This is a requirement of the change that. This is a requirement of the change that. This is a requirement of the gameplay. But gameplay. But we can we can distribute those distance calculations. We distribute those distance calculations. We distribute those distance calculations. We divide our group into divide our group into divide our group into four parts. So, four parts. So, four parts. So, frame one—that's enemies frame one—that's enemies frame one—that's enemies 1 to 25, then 26 to 50, 1 to 25, then 26 to 50, 1 to 25, then 26 to 50, and so on. And on the and so on. And on the and so on. And on the fifth frame we fifth frame we fifth frame we start again with the start again with the start again with the first group. So, from an first group. So, from an first group. So, from an individual individual individual enemy perspective, nothing has enemy perspective, nothing has enemy perspective, nothing has changed compared changed compared changed compared to the previous to the previous to the previous optimization. They optimization. They optimization. They still do still do still do something every something every something every fourth frame. But fourth frame. But fourth frame. But now we just now we just use certain use certain frames to have fewer frames to have fewer frames to have fewer calls but calls but calls but do the same do the same do the same job. So we're job. So we're job. So we're still updating still updating still updating the distance every the distance every the distance every four frames, but in four frames, but in four frames, but in terms of a frame, uh, terms of a frame, uh, terms of a frame, uh, now we're now we're now we're only checking a quarter of only checking a quarter of only checking a quarter of the population. It could the population. It could the population. It could be, it could be a different be, it could be a different be, it could be a different number, but for us it's a number, but for us it's a number, but for us it's a part of the population.
-
part of the population. So now there's less work in the frame So now there's less work in the frame and we and we and we have some of the have some of the have some of the cuts we cuts we cuts we wanted to get. And wanted to get. And wanted to get. And now we're profiling now we're profiling now we're profiling again, and we, uh, we again, and we, uh, we had, before this change, I recall, 4.2 had, before this change, I recall, 4.2 milliseconds. Now, milliseconds. Now, milliseconds. Now, after this after this after this division, we have 3.8 division, we have 3.8 . So we recovered, uh . So we recovered, uh , 0.4 milliseconds. And I , 0.4 milliseconds. And I , 0.4 milliseconds. And I know that doesn't sound know that doesn't sound know that doesn't sound very exciting, but very exciting, but very exciting, but remember that what we remember that what we remember that what we really changed is really changed is really changed is because we didn't because we didn't because we didn't rewrite rewrite rewrite the algorithm, we didn't the algorithm, we didn't the algorithm, we didn't implement a implement a implement a complex complex complex data structure, we didn't data structure, we didn't data structure, we didn't speed up individual speed up individual speed up individual calculations. We just calculations. We just calculations. We just stopped doing stopped doing stopped doing some of the work, and, uh, some of the work, and, uh, some of the work, and, uh, we do that work we do that work we do that work as often as often as often as necessary, not as as necessary, not as as necessary, not as often as possible. And, often as possible. And, often as possible. And, importantly, uh, we importantly, uh, we importantly, uh, we know it know it know it helped because we helped because we helped because we measured it. This is it, this is it measured it. This is it, this is it measured it. This is it, this is it , this is really , this is really , this is really important. So, we important. So, we important. So, we had a hypothesis, we had a hypothesis, we had a hypothesis, we changed the planning, changed the planning, changed the planning, we profiled again, we profiled again, we profiled again, and now we have a and now we have a and now we have a real result.
-
real result. So this is very important So this is very important when you when you when you optimize something: don't optimize something: don't optimize something: don't do it blindly, do it blindly, do it blindly, just profile just profile just profile once, do once, do once, do something, profile something, profile something, profile a second time, and then a second time, and then a second time, and then work further if work further if work further if necessary. This, this is necessary. This, this is necessary. This, this is how you should, you how you should, you how you should, you should, uh, should, uh, should, uh, handle this. handle this. handle this. Good. So, the first Good. So, the first Good. So, the first reduction reduction reduction was related to frequency. was related to frequency. was related to frequency. We look at the work We look at the work that happens that happens that happens frame by frame and frame by frame and frame by frame and ask, "Does ask, "Does ask, "Does this really have to this really have to this really have to happen so happen so happen so often?" And that already often?" And that already often?" And that already bought us, uh, bought us, uh, bought us, uh, a little time. But a little time. But a little time. But decreasing frequency decreasing frequency decreasing frequency still means still means still means we do the same thing over and over again we do the same thing over and over again we do the same thing over and over again . So, we have a . So, we have a . So, we have a certain period of time certain period of time certain period of time to take action. And we to take action. And we to take action. And we still ask still ask still ask the question over and the question over and the question over and over again, or we over again, or we over again, or we bring it up over and over again bring it up over and over again bring it up over and over again . So maybe the . So maybe the . So maybe the next optimization next optimization next optimization isn't to isn't to isn't to query less often. query less often. query less often. Maybe we should Maybe we should Maybe we should consider whether we should consider whether we should consider whether we should ask at all. ask at all. ask at all. Maybe we should Maybe we should Maybe we should stop asking stop asking , and that's the next thing we , and that's the next thing we , and that's the next thing we want to do. want to do. want to do. So, let's get back to So, let's get back to So, let's get back to our cat. And our cat. And our cat. And after the first after the first after the first reduction, we reduction, we reduction, we figured out how to figured out how to figured out how to update the distance update the distance update the distance to the player. It's no longer something that to the player. It's no longer something that to the player. It's no longer something that every enemy has to every enemy has to every enemy has to calculate every calculate every calculate every frame. So frame. So frame. So let's now let's now let's now look at another look at another look at another function function function called "update state" called "update state" . So . So . So what does what does what does this feature actually do? Let me remind you, in this feature actually do? Let me remind you, in this feature actually do? Let me remind you, in our example, it our example, it our example, it checks the checks the checks the enemy's health, updates the enemy's health, updates the enemy's health, updates the health bar, and destroys the health bar, and destroys the health bar, and destroys the enemy if the health enemy if the health enemy if the health reaches zero. And reaches zero. And reaches zero. And now we're forcing now we're forcing now we're forcing him to check this him to check this him to check this condition again, and again, and condition again, and again, and condition again, and again, and again. So, every
-
again. So, every again. So, every frame we check frame we check frame we check and ask, "Oh, are you and ask, "Oh, are you and ask, "Oh, are you alive? Oh, are you alive?" and alive? Oh, are you alive?" and alive? Oh, are you alive?" and the like. And we the like. And we the like. And we could use could use could use the same trick here as we did a the same trick here as we did a the same trick here as we did a few minutes ago. few minutes ago. So, run it So, run it every second frame, every second frame, every second frame, every fifth frame, or every fifth frame, or every fifth frame, or with a different period. But, with a different period. But, with a different period. But, of course, this would reduce of course, this would reduce of course, this would reduce costs, but the costs, but the costs, but the main question here is: main question here is: main question here is: why are we checking this at all why are we checking this at all why are we checking this at all ? There may ? There may ? There may be a better solution to be a better solution to be a better solution to achieve the achieve the achieve the same result, same result, same result, but without these challenges but without these challenges but without these challenges in every frame. So, in every frame. So, in every frame. So, let's see let's see let's see what what what update state actually does. For this update state actually does. For this update state actually does. For this example, the important example, the important example, the important part is health. part is health. part is health. So, in the first frame So, in the first frame So, in the first frame we have 100 we have 100 we have 100 health, we health, we health, we summon it. summon it. summon it. Second frame, third Second frame, third Second frame, third frame—the same thing. And then in the frame—the same thing. And then in the frame—the same thing. And then in the fourth frame fourth frame fourth frame something happens and something happens and something happens and the health drops to 75. the health drops to 75. the health drops to 75. Now we also Now we also Now we also summon it, and summon it, and summon it, and after that after that after that we summon it even we summon it even we summon it even if the health doesn't if the health doesn't if the health doesn't change. So change. So change. So we have 75, and the next we have 75, and the next we have 75, and the next frame could be 75 too.
-
frame could be 75 too. frame could be 75 too. So just from this So just from this So just from this table you can see: table you can see: table you can see: you have five calls and you have five calls and you have five calls and only one actual only one actual only one actual change. That is, only change. That is, only change. That is, only one frame was one frame was one frame was important. The rest important. The rest important. The rest were really were really were really unimportant. So, with the unimportant. So, with the unimportant. So, with the previous previous previous problem, the question problem, the question problem, the question was: does this really have to was: does this really have to was: does this really have to happen in happen in happen in every frame? That every frame? That every frame? That was our question. was our question. was our question. Here I want to ask a Here I want to ask a Here I want to ask a slightly different question. slightly different question. slightly different question. Is it Is it Is it even necessary to check it even necessary to check it even necessary to check it when nothing when nothing when nothing has changed? Because has changed? Because has changed? Because if health if health if health only changes when only changes when only changes when something happens to something happens to something happens to the enemy, perhaps the the enemy, perhaps the the enemy, perhaps the change in health itself change in health itself change in health itself can tell us can tell us can tell us when this work is when this work is when this work is needed. When needed. When needed. When health changes, health changes, health changes, it will tell us, "Okay, it will tell us, "Okay, it will tell us, "Okay, I changed the meaning. I changed the meaning. I changed the meaning. You can do something about it You can do something about it You can do something about it ." Or not. ." Or not. ." Or not. Like, "the decision is Like, "the decision is Like, "the decision is yours." But this is the yours." But this is the yours." But this is the information you information you information you can get. So can get. So , how do we change the , how do we change the , how do we change the approach? So, this is our approach? So, this is our approach? So, this is our approach. Instead of approach. Instead of asking each cadre if their health has changed asking each cadre if their health has changed , we simply , we simply , we simply do nothing. do nothing. do nothing. So, from the first to the So, from the first to the So, from the first to the third frame, no work is third frame, no work is third frame, no work is performed. We do performed. We do performed. We do n't do anything and we don't n't do anything and we don't n't do anything and we don't cause it. And cause it. And cause it. And then, in the fourth then, in the fourth then, in the fourth frame, the enemy takes frame, the enemy takes frame, the enemy takes damage. The health damage. The health damage. The health changes to 75. And that changes to 75. And that changes to 75. And that 's when we want to 's when we want to 's when we want to call update state to call update state to call update state to update the update the update the health bar or whatever else health bar or whatever else health bar or whatever else we need.
-
we need. And in the fifth frame, And in the fifth frame, nothing nothing nothing changed again. So, changed again. So, changed again. So, nothing to do. And the nothing to do. And the nothing to do. And the outcome of the gameplay outcome of the gameplay outcome of the gameplay remains remains remains unchanged. The enemy unchanged. The enemy unchanged. The enemy still reacts instantly still reacts instantly still reacts instantly when when when health changes, but we health changes, but we health changes, but we change the moment of change the moment of change the moment of doing the job. doing the job. Previously, the system Previously, the system would constantly ask, would constantly ask, would constantly ask, "Did something happen? Did "Did something happen? Did "Did something happen? Did something happen? Did something something happen? Did something something happen? Did something happen?" Now the event happen?" Now the event happen?" Now the event itself tells us, "Okay itself tells us, "Okay , you need to , you need to , you need to do the work because do the work because do the work because something happened." This doesn't something happened." This doesn't something happened." This doesn't mean that everything has to mean that everything has to mean that everything has to be exactly like this. be exactly like this. So we want to So we want to move to a specific move to a specific event-driven model. So, we have a event-driven model. So, we have a certain action, and we certain action, and we certain action, and we need to react to it need to react to it need to react to it . And this does . And this does . And this does not mean at all that not mean at all that not mean at all that we should change we should change we should change everything to this approach. everything to this approach. Frequent requests, like we Frequent requests, like we do now, have do now, have do now, have their own valid their own valid use cases.
-
The question is whether The question is whether we ask because we we ask because we we ask because we really need really need really need time observation, time observation, time observation, or simply because of or simply because of or simply because of convenience. Because if you don't convenience. Because if you don't convenience. Because if you don't need to ask need to ask need to ask constantly, maybe you constantly, maybe you constantly, maybe you shouldn't do it shouldn't do it . In this case, we . In this case, we . In this case, we control the operation control the operation that changes health. that changes health. that changes health. We already have the perfect We already have the perfect We already have the perfect moment to react moment to react moment to react because we can because we can because we can go to where go to where go to where health is changing health is changing health is changing and just send and just send and just send the information to our the information to our the information to our systems. But this is not systems. But this is not systems. But this is not always the case. However, in always the case. However, in always the case. However, in this particular this particular this particular case, that is exactly the case. case, that is exactly the case. case, that is exactly the case. So, we can So, we can So, we can use that. But I use that. But I use that. But I want to say that this is not the want to say that this is not the want to say that this is not the only perfect only perfect only perfect rule. You can't rule. You can't rule. You can't use this use this use this everywhere. You need to everywhere. You need to everywhere. You need to think about what you think about what you think about what you want to achieve and what want to achieve and what want to achieve and what resources you have. And that resources you have. And that resources you have. And that brings us, as I brings us, as I brings us, as I said, to a said, to a said, to a similar daily- similar daily- driven version. driven version. So, something So, something harms our enemy, harms our enemy, harms our enemy, health changes, health changes, health changes, and it is at this moment that we and it is at this moment that we and it is at this moment that we know that know that know that something important has happened. And we something important has happened. And we something important has happened. And we broadcast this broadcast this broadcast this information through all information through all information through all systems. Now systems. Now anyone who is subscribed anyone who is subscribed anyone who is subscribed at this point and is at this point and is at this point and is interested in the fact interested in the fact interested in the fact that the state has changed that the state has changed that the state has changed can react.
-
can react. The interface can The interface can update the update the update the health bar, the game health bar, the game health bar, the game logic can check logic can check logic can check if the enemy should die, if the enemy should die, if the enemy should die, the other systems can the other systems can do whatever they do whatever they do whatever they need to. That's how it is need to. That's how it is need to. That's how it is . But remember . But remember . But remember that events are not that events are not that events are not free. free. free. Delegates have Delegates have Delegates have call costs, call costs, call costs, subscriptions are a matter of subscriptions are a matter of subscriptions are a matter of object lifetime, and object lifetime, and object lifetime, and any complex any complex any complex architecture is difficult architecture is difficult architecture is difficult to track. And if to track. And if to track. And if you have a lot of events being you have a lot of events being you have a lot of events being triggered at the same triggered at the same triggered at the same time, time, time, such as an such as an such as an execution order, then execution order, then execution order, then debugging what's debugging what's debugging what's happening can happening can happening can be very difficult. And be very difficult. And be very difficult. And sometimes this can sometimes this can sometimes this can cause cause cause bottlenecks. So you can't bottlenecks. So you can't bottlenecks. So you can't just replace everything just replace everything just replace everything with delegates, with delegates, with delegates, hoping that hoping that hoping that the number of calls will the number of calls will the number of calls will significantly decrease. The significantly decrease. The lesson is that if lesson is that if a job only exists a job only exists a job only exists because something because something because something has changed, consider has changed, consider has changed, consider doing it right doing it right doing it right at the moment of change, rather than at the moment of change, rather than at the moment of change, rather than constantly whenever constantly whenever constantly whenever possible. Let's go back possible. Let's go back possible. Let's go back to our internal to our internal to our internal processes. We started processes. We started processes. We started with about 4.2 with about 4.2 with about 4.2 milliseconds for these 50 milliseconds for these 50 milliseconds for these 50 enemies. Now we've enemies. Now we've enemies. Now we've removed another removed another removed another category of unnecessary category of unnecessary category of unnecessary work, and we have work, and we have work, and we have about 3.2 about 3.2 about 3.2 milliseconds. This isn't milliseconds. This isn't milliseconds. This isn't some amazing some amazing some amazing optimization, but we've optimization, but we've optimization, but we've reduced the time by another 0.4 reduced the time by another 0.4 reduced the time by another 0.4 milliseconds. So milliseconds. So milliseconds. So now we have 0.6 now we have 0.6 now we have 0.6 if we add that up.
-
if we add that up. About 0.6 after About 0.6 after these two reductions, these two reductions, these two reductions, so we gained so we gained so we gained about 1 millisecond about 1 millisecond . But we didn't write a . But we didn't write a . But we didn't write a better better better distance algorithm, distance algorithm, distance algorithm, optimize the optimize the optimize the health check, or health check, or health check, or do anything do anything do anything tricky with memory. tricky with memory. tricky with memory. We mostly We mostly We mostly changed the timing of the changed the timing of the changed the timing of the work or work or work or decided whether to decided whether to do it at all. This is a pretty do it at all. This is a pretty good result good result good result for us. So far, we've for us. So far, we've for us. So far, we've optimized when optimized when optimized when each enemy each enemy each enemy does their job. does their job. does their job. First, we reduced First, we reduced First, we reduced the execution frequency. the execution frequency. Secondly, we removed it altogether Secondly, we removed it altogether Secondly, we removed it altogether . But there is . But there is . But there is another assumption that another assumption that another assumption that we haven't touched on at all, and we haven't touched on at all, and we haven't touched on at all, and I want to quickly I want to quickly I want to quickly touch on it touch on it touch on it now. Why, exactly, does now. Why, exactly, does now. Why, exactly, does every enemy have to every enemy have to every enemy have to do this work themselves? do this work themselves? do this work themselves? This is our third This is our third This is our third reduction, which I reduction, which I reduction, which I called "ownership." called "ownership." called "ownership." But by ownership I But by ownership I But by ownership I don't mean don't mean don't mean ownership in C++ or ownership in C++ or ownership in C++ or memory lifetime. I mean memory lifetime. I mean memory lifetime. I mean what what what part of the part of the part of the game architecture is responsible for game architecture is responsible for game architecture is responsible for being aware of something being aware of something being aware of something and making decisions and making decisions and making decisions about processing time. This is where about processing time. This is where we we move on to the move on to the move on to the third feature— third feature— progress updates.
-
progress updates. Placing this Placing this inside a tick inside a tick inside a tick seems seems seems intuitive, as the intuitive, as the intuitive, as the enemy moves enemy moves enemy moves every frame, so we every frame, so we every frame, so we need to check need to check need to check every frame what the every frame what the path's progress looks like. This feature path's progress looks like. This feature tracks how tracks how tracks how far the enemy far the enemy far the enemy has advanced along its has advanced along its has advanced along its route and route and route and displays on the displays on the displays on the interface interface interface how many percent how many percent how many percent it has approached us it has approached us it has approached us as a player. We as a player. We as a player. We use this use this use this information for information for information for gameplay. We gameplay. We gameplay. We use it use it use it for the interface. We for the interface. We for the interface. We use it in use it in use it in all other all other all other places. So, at places. So, at places. So, at first glance, first glance, first glance, adding this to the adding this to the adding this to the enemy in the queue enemy in the queue enemy in the queue seems completely seems completely seems completely reasonable. But this is the reasonable. But this is the reasonable. But this is the enemy's progress. So, enemy's progress. So, enemy's progress. So, this is the enemy's progress, this is the enemy's progress, this is the enemy's progress, so it's obvious that the so it's obvious that the so it's obvious that the enemy must enemy must enemy must calculate their own calculate their own calculate their own progress. But even progress. But even progress. But even if the enemy possesses if the enemy possesses if the enemy possesses this data, it does not this data, it does not this data, it does not mean that he mean that he mean that he must know about the must know about the must know about the operation itself. And why is operation itself. And why is operation itself. And why is that? Because in our that? Because in our that? Because in our example, this enemy example, this enemy example, this enemy doesn't actually exist doesn't actually exist doesn't actually exist in isolation. They already in isolation. They already in isolation. They already belong to something belong to something belong to something bigger. And it's something bigger. And it's something bigger. And it's something more—a line. So, more—a line. So, more—a line. So, enemy one is moving enemy one is moving enemy one is moving along the same line as along the same line as along the same line as enemy two, four, and enemy two, four, and enemy two, four, and seven, but they don't seven, but they don't seven, but they don't know about know about know about each other. They don't each other. They don't each other. They don't care about each care about each care about each other. From a other. From a other. From a gameplay perspective, gameplay perspective, gameplay perspective, they are separate they are separate they are separate objects, but from a
-
objects, but from a objects, but from a broader perspective, broader perspective, broader perspective, they are part of the they are part of the they are part of the same structure. And same structure. And same structure. And these structures contain these structures contain these structures contain information that we information that we information that we can use, can use, can use, because now each enemy because now each enemy because now each enemy individually asks: “Where am I individually asks: “Where am I individually asks: “Where am I on my line? Have on my line? Have on my line? Have I reached the end? What I reached the end? What I reached the end? What should happen because of this? should happen because of this? » But perhaps an » But perhaps an » But perhaps an individual enemy is not the individual enemy is not the individual enemy is not the best place to best place to best place to answer these answer these answer these questions, because instead of questions, because instead of questions, because instead of thinking about 100, 50, or thinking about 100, 50, or thinking about 100, 50, or whatever number of whatever number of whatever number of independent enemies, independent enemies, independent enemies, we can start we can start we can start thinking about groups of thinking about groups of thinking about groups of enemies and enemies and enemies and use that use that use that information. So, we information. So, we information. So, we can move the can move the can move the call to this function to a call to this function to a call to this function to a system that system that system that will manage the entire will manage the entire will manage the entire process. Of course, process. Of course, process. Of course, simply moving simply moving simply moving the cycle doesn't make it the cycle doesn't make it the cycle doesn't make it faster, but now we faster, but now we faster, but now we get control get control get control over the population. So, over the population. So, over the population. So, we implement a we implement a we implement a line system, line system, line system, instead of instead of instead of each frame each frame each frame being updated individually, and the line being updated individually, and the line being updated individually, and the line knows which enemies knows which enemies knows which enemies belong to it. But belong to it. But belong to it. But we have we have we have n't optimized anything yet. So n't optimized anything yet. So n't optimized anything yet. So if 100 enemies if 100 enemies if 100 enemies performed an operation performed an operation performed an operation before, and now the before, and now the before, and now the line system line system line system cycles cycles cycles through those 100 enemies and through those 100 enemies and through those 100 enemies and performs the same performs the same performs the same operation, we still operation, we still operation, we still have roughly the have roughly the have roughly the same amount of work.
-
same amount of work. So, there is no So, there is no optimization here, but the optimization here, but the optimization here, but the ownership of the data has changed ownership of the data has changed ownership of the data has changed . We now . We now . We now have one place that have one place that have one place that understands the entire understands the entire understands the entire population. And with that, population. And with that, population. And with that, we can begin to we can begin to we can begin to make decisions that an make decisions that an make decisions that an individual enemy simply could individual enemy simply could individual enemy simply could not make. not make. not make. So we received So we received So we received information that can be information that can be information that can be usefully used usefully used usefully used for optimization. for optimization. for optimization. Thus, we Thus, we Thus, we create an opportunity create an opportunity create an opportunity for optimization. And that's exactly what for optimization. And that's exactly what for optimization. And that's exactly what I mean I mean I mean by gaining by gaining by gaining control over the control over the control over the population. An individual population. An individual population. An individual enemy knows about itself, enemy knows about itself, enemy knows about itself, perhaps about the player, perhaps about the player, perhaps about the player, but it does not understand but it does not understand but it does not understand the population to which it the population to which it the population to which it belongs. But the belongs. But the belongs. But the line system understands this. He line system understands this. He line system understands this. He knows how many knows how many knows how many enemies there are, where they enemies there are, where they enemies there are, where they are, and which of are, and which of are, and which of them are really important at them are really important at them are really important at this moment. More this moment. More this moment. More importantly, he can importantly, he can importantly, he can decide how to decide how to decide how to distribute the work distribute the work distribute the work among the entire group. And this is where among the entire group. And this is where property rights become a property rights become a tool for tool for tool for increasing increasing increasing productivity. productivity. productivity. Ownership does not reduce Ownership does not reduce Ownership does not reduce the amount of work, it the amount of work, it the amount of work, it gives us the ability gives us the ability gives us the ability to decide where that to decide where that to decide where that work is done. And work is done. And work is done. And this is a solution for us, because this is a solution for us, because this is a solution for us, because now the path system now the path system now the path system knows something that the knows something that the knows something that the individual enemy did not know. These individual enemy did not know. These individual enemy did not know. These enemies are not just 100 enemies are not just 100 enemies are not just 100 unrelated actors, unrelated actors, unrelated actors, they are part of the they are part of the they are part of the same path. And this same path. And this same path. And this means that not every means that not every means that not every enemy is equally enemy is equally enemy is equally important. If I'm important. If I'm important. If I'm wondering if an wondering if an wondering if an enemy is nearing the enemy is nearing the enemy is nearing the end of the path, I do end of the path, I do end of the path, I do n't need all n't need all n't need all 100 enemies checking 100 enemies checking 100 enemies checking their progress. The path their progress. The path their progress. The path already knows which
-
already knows which already knows which enemy is leading. So enemy is leading. So enemy is leading. So for this particular for this particular for this particular operation, I might operation, I might only be interested in enemies seven, only be interested in enemies seven, eight, and six, for example. So, eight, and six, for example. So, eight, and six, for example. So, we didn't update the we didn't update the we didn't update the progress function, we progress function, we progress function, we didn't speed it up, didn't speed it up, didn't speed it up, we just changed we just changed we just changed the number of objects the number of objects the number of objects executing it. executing it. executing it. After this change, After this change, After this change, the indicator dropped from 3.2 to the indicator dropped from 3.2 to the indicator dropped from 3.2 to 2.9 ms, that is, by another 0.3 ms 2.9 ms, that is, by another 0.3 ms . We didn't do anything . We didn't do anything . We didn't do anything complicated, but complicated, but complicated, but notice what exactly we notice what exactly we notice what exactly we did in all these did in all these did in all these steps. We didn't steps. We didn't steps. We didn't optimize optimize optimize the math, the math, the math, replace the algorithms, replace the algorithms, replace the algorithms, or try to or try to or try to radically radically radically speed up a single speed up a single speed up a single function. We started function. We started function. We started asking other asking other asking other questions. Do I questions. Do I questions. Do I need to need to need to run this? How often? run this? How often? run this? How often? Who should be responsible Who should be responsible Who should be responsible for this work? And so for this work? And so for this work? And so on. We started with 4.2, on. We started with 4.2, on. We started with 4.2, and now we have 2.9. and now we have 2.9. and now we have 2.9. Same gameplay, Same gameplay, Same gameplay, but different decisions about but different decisions about but different decisions about when and where when and where when and where work is done. And work is done. And work is done. And that is the key to that is the key to that is the key to optimization in this optimization in this optimization in this case. Let's try case. Let's try case. Let's try to summarize what we to summarize what we to summarize what we learned today. Our learned today. Our learned today. Our first step was first step was first step was about frequency.
-
about frequency. about frequency. We stopped We stopped We stopped assuming that every assuming that every assuming that every update had to update had to update had to happen in happen in happen in every frame. It every frame. It every frame. It was simple. was simple. was simple. Do the work as Do the work as Do the work as often as necessary, often as necessary, often as necessary, not as often as not as often as not as often as possible. This is our possible. This is our possible. This is our first lesson. In first lesson. In first lesson. In the second step, to the second step, to the second step, to change the state, we change the state, we change the state, we no longer need to no longer need to no longer need to ask questions. We ask questions. We ask questions. We just wait for just wait for just wait for the system to tell the system to tell the system to tell us that something happened. us that something happened. So, instead of So, instead of doing the work doing the work doing the work periodically, we do periodically, we do periodically, we do it on demand, and we it on demand, and we it on demand, and we get another get another get another boost. And the third boost. And the third boost. And the third step provided more step provided more step provided more context, context, context, allowing us allowing us allowing us to decide what exactly to decide what exactly to decide what exactly needed updating. And the needed updating. And the needed updating. And the same result same result same result is achieved with less is achieved with less is achieved with less effort, that's where we effort, that's where we effort, that's where we find ourselves. So what did find ourselves. So what did find ourselves. So what did we actually we actually we actually learn from all these learn from all these learn from all these three steps? We three steps? We three steps? We started with the assumption started with the assumption started with the assumption that if something can be that if something can be that if something can be updated every frame, updated every frame, updated every frame, then it should be done every then it should be done every then it should be done every frame. But this is not a frame. But this is not a frame. But this is not a technical requirement, it is a technical requirement, it is a technical requirement, it is a game requirement. So, game requirement. So, game requirement. So, the position needed the position needed the position needed frequent updates, and frequent updates, and frequent updates, and the distance didn't the distance didn't the distance didn't need to be as need to be as need to be as precise. So precise. So precise. So instead of asking, "How can I instead of asking, "How can I instead of asking, "How can I make this upgrade make this upgrade make this upgrade cheaper?" we first cheaper?" we first cheaper?" we first asked, "How often does this asked, "How often does this asked, "How often does this actually have to actually have to actually have to happen?" And then, as we happen?" And then, as we happen?" And then, as we reduced the frequency, we reduced the frequency, we reduced the frequency, we saw something else saw something else saw something else important. Average important. Average important. Average frame time isn't everything.
-
frame time isn't everything. frame time isn't everything. If we move If we move If we move all the work to one all the work to one all the work to one frame, we will encounter frame, we will encounter load spikes. So, load spikes. So, planning also planning also planning also means thinking about means thinking about means thinking about when work is done when work is done when work is done and how it is and how it is and how it is distributed. In distributed. In distributed. In the second approach, we the second approach, we the second approach, we looked at the looked at the looked at the update state, which update state, which update state, which was essentially a constant was essentially a constant was essentially a constant repetition of the same repetition of the same repetition of the same question. And question. And question. And for the most part, for the most part, for the most part, the answer was that there was the answer was that there was the answer was that there was nothing to be done nothing to be done nothing to be done . We already . We already . We already knew exactly when our knew exactly when our knew exactly when our health was changing, health was changing, health was changing, so instead of so instead of so instead of constantly asking constantly asking constantly asking about our current state, we about our current state, we about our current state, we responded to the event responded to the event responded to the event that changed it. So, that changed it. So, that changed it. So, the principle here is: don't the principle here is: don't the principle here is: don't act when you can act when you can act when you can react. So, react. So, react. So, if a certain job if a certain job if a certain job exists only because you exists only because you exists only because you expect change, expect change, expect change, see if see if see if those changes can be a those changes can be a those changes can be a trigger for the job. trigger for the job. And finally, possession. And finally, possession. This was a bit different. This was a bit different. This was a bit different. We didn't necessarily We didn't necessarily We didn't necessarily make the operation make the operation make the operation cheaper, we changed cheaper, we changed cheaper, we changed who was responsible who was responsible who was responsible for deciding to for deciding to for deciding to carry it out. Previously, carry it out. Previously, carry it out. Previously, each enemy each enemy each enemy updated updated updated independently, and each independently, and each independently, and each enemy had a very enemy had a very enemy had a very limited view of the limited view of the limited view of the world. But our world. But our world. But our enemies already belonged enemies already belonged enemies already belonged to lineages, and by shifting to lineages, and by shifting to lineages, and by shifting responsibility to the responsibility to the responsibility to the lineage system, we lineage system, we lineage system, we suddenly had suddenly had suddenly had knowledge of the entire knowledge of the entire knowledge of the entire population, and that population, and that population, and that opened up opportunities opened up opportunities opened up opportunities for optimization. So for optimization. So , this architectural , this architectural , this architectural change allowed us change allowed us change allowed us to share more to share more to share more information, and we information, and we information, and we were able to make were able to make were able to make more accurate decisions.
-
more accurate decisions. There is one part of There is one part of the equation that we have the equation that we have the equation that we have n't n't n't touched on today. Everything we've touched on today. Everything we've touched on today. Everything we've done before done before done before has assumed that each has assumed that each has assumed that each individual operation is individual operation is individual operation is fairly cheap. And fairly cheap. And fairly cheap. And then we asked then we asked then we asked if we were doing it too often if we were doing it too often if we were doing it too often or for or for or for too many too many too many objects. objects. objects. But sometimes that's But sometimes that's But sometimes that's not the problem at all, of not the problem at all, of not the problem at all, of course. Sometimes course. Sometimes course. Sometimes the work itself is simply the work itself is simply the work itself is simply expensive. Maybe it's an expensive. Maybe it's an expensive. Maybe it's an algorithm that doesn't algorithm that doesn't algorithm that doesn't scale well, scale well, scale well, maybe we're constantly maybe we're constantly maybe we're constantly jumping around in memory, jumping around in memory, jumping around in memory, maybe we have a maybe we have a maybe we have a large amount of work large amount of work large amount of work that can be batched, that can be batched, that can be batched, parallelized, or something parallelized, or something parallelized, or something like that. And at this like that. And at this like that. And at this point we move point we move point we move into a completely different area of into a completely different area of performance engineering. So performance engineering. So we can start we can start we can start looking at algorithms looking at algorithms . We can start . We can start . We can start thinking about thinking about thinking about data structure. We can data structure. We can data structure. We can look for opportunities look for opportunities look for opportunities to batch process to batch process to batch process or perform other or perform other or perform other work. Eventually, work. Eventually, work. Eventually, depending on the scale of depending on the scale of depending on the scale of the problem, we might the problem, we might the problem, we might start thinking about start thinking about start thinking about object-oriented object-oriented object-oriented design, ECS, or design, ECS, or design, ECS, or something like Mass.
-
something like Mass. So, these are all important So, these are all important tools, and each tools, and each tools, and each of them could be the of them could be the of them could be the subject of a separate subject of a separate subject of a separate report. I don't want to report. I don't want to report. I don't want to start the conversation with start the conversation with start the conversation with this, because before this, because before this, because before rushing into any rushing into any rushing into any operation, I want operation, I want operation, I want you to understand whether you to understand whether you to understand whether it needs to be performed at all it needs to be performed at all it needs to be performed at all . If I . If I . If I can do something can do something can do something twice as fast—that's twice as fast—that's twice as fast—that's great. But if I great. But if I great. But if I can avoid 90% of that can avoid 90% of that can avoid 90% of that work—that's a much work—that's a much work—that's a much bigger victory. So bigger victory. So when I see a when I see a when I see a performance problem, I performance problem, I performance problem, I go back to these go back to these go back to these three questions. So, three questions. So, three questions. So, how effectively is how effectively is how effectively is the work being done? the work being done? the work being done? How often do we do this? How often do we do this? And for how many And for how many objects do we have to objects do we have to objects do we have to do this? You shouldn't do this? You shouldn't do this? You shouldn't immediately assume immediately assume immediately assume that cost is the that cost is the that cost is the indicator that indicator that indicator that needs to be needs to be needs to be optimized. Sometimes optimized. Sometimes optimized. Sometimes it is, sometimes it is not. It it is, sometimes it is not. It it is, sometimes it is not. It depends on the depends on the depends on the situation. The best situation. The best situation. The best optimization optimization optimization happens before happens before happens before the function even the function even the function even starts executing starts executing . If you take away . If you take away . If you take away only only only one thing from this report, one thing from this report, one thing from this report, remember: remember: remember: the cheapest work the cheapest work is the work you can avoid is the work you can avoid is the work you can avoid doing. This will doing. This will doing. This will end this end this end this topic for now. Thank you for your topic for now. Thank you for your topic for now. Thank you for your attention. If you have any attention. If you have any attention. If you have any questions, I'd be questions, I'd be questions, I'd be happy to answer them happy to answer them happy to answer them if we still have time. That's all for now if we still have time. That's all for now if we still have time. That's all for now .
-
. Thank you very much, Conrad. Thank you very much, Conrad. It was a wonderful It was a wonderful It was a wonderful pragmatic report pragmatic report . So many practical . So many practical . So many practical tips. It is immediately apparent tips. It is immediately apparent tips. It is immediately apparent that this is knowledge gained that this is knowledge gained that this is knowledge gained through real-world through real-world through real-world experience in the industry. experience in the industry. Yes, that's true. I won't Yes, that's true. I won't even argue with that even argue with that even argue with that . I'm glad . I'm glad . I'm glad you liked it, you liked it, you liked it, because this is a topic that I because this is a topic that I because this is a topic that I really like to talk about, really like to talk about, really like to talk about, because in my because in my because in my opinion, there are not enough of such topics right now. opinion, there are not enough of such topics right now. So. It's great that the tips It's great that the tips are applicable to so are applicable to so are applicable to so many things: to many things: to many things: to different game different game different game engines and even to engines and even to engines and even to developing developing developing real-time solutions in real-time solutions in real-time solutions in other industries—all of these are other industries—all of these are other industries—all of these are very effective things that very effective things that very effective things that can be used can be used can be used anywhere. anywhere. Yes, that's true. Yes, that's true. Daniel, I think Daniel, I think Daniel, I think we have a question, don't we we have a question, don't we we have a question, don't we ? ? ? Yes, there is. Thanks again for Yes, there is. Thanks again for Yes, there is. Thanks again for the report, Conrad. These are, the report, Conrad. These are, the report, Conrad. These are, yes, really useful yes, really useful yes, really useful ideas. So, one of ideas. So, one of ideas. So, one of the questions in the chat from the questions in the chat from the questions in the chat from Rulock. I hope I'm Rulock. I hope I'm Rulock. I hope I'm pronouncing it correctly.
-
pronouncing it correctly. He was asking, do He was asking, do you have a vision or an you have a vision or an you have a vision or an ideal distribution ideal distribution ideal distribution of what is done behind the of what is done behind the of what is done behind the scenes? For example, do scenes? For example, do scenes? For example, do you spend 50% on you spend 50% on you spend 50% on gameplay and 15% on the engine? gameplay and 15% on the engine? gameplay and 15% on the engine? How do you distribute all this How do you distribute all this How do you distribute all this ? I ? I don't know if I have an don't know if I have an ideal vision ideal vision ideal vision for this, because it all for this, because it all for this, because it all depends a lot on the depends a lot on the depends a lot on the situation. Because you situation. Because you situation. Because you can't say: "Okay, can't say: "Okay, can't say: "Okay, I'll spend this much on I'll spend this much on I'll spend this much on gameplay, and this much gameplay, and this much on the engine." Because sometimes there is on the engine." Because sometimes there is on the engine." Because sometimes there is room for room for room for gameplay optimization gameplay optimization , and sometimes there is room for engine optimization. So , and sometimes there is room for engine optimization. So , and sometimes there is room for engine optimization. So if I hit an optimization " if I hit an optimization " bottleneck" bottleneck" bottleneck" where I where I where I can't can't can't do anything with the engine. I do anything with the engine. I do anything with the engine. I could try, could try, could try, you know, to perform some kind of you know, to perform some kind of you know, to perform some kind of miracle. But I can't miracle. But I can't miracle. But I can't do that. Then I'll do that. Then I'll do that. Then I'll look elsewhere look elsewhere look elsewhere . So you can't . So you can't . So you can't have one magic have one magic have one magic rule to say, rule to say, rule to say, "Okay, this percentage is "Okay, this percentage is "Okay, this percentage is for the engine, this percentage is for the for the engine, this percentage is for the for the engine, this percentage is for the gameplay." You have to gameplay." You have to gameplay." You have to assess your assess your assess your situation, look at situation, look at situation, look at where all the time is being spent where all the time is being spent where all the time is being spent , and just , and just , and just try to decide: try to decide: try to decide: okay, I'm not going to do much here okay, I'm not going to do much here okay, I'm not going to do much here , because it's , because it's , because it's only a only a only a few microseconds, for example. I few microseconds, for example. I few microseconds, for example. I can't save can't save can't save even a microsecond.
-
even a microsecond. even a microsecond. That wouldn't make much That wouldn't make much That wouldn't make much sense. So sense. So sense. So we need to look we need to look we need to look elsewhere. So, elsewhere. So, elsewhere. So, I don't have a vision of a I don't have a vision of a I don't have a vision of a perfect magic perfect magic perfect magic rule. You have a rule. You have a rule. You have a profiler. You should profiler. You should profiler. You should look at look at look at the profiler and see the profiler and see the profiler and see what can be done and what what can be done and what what can be done and what can be changed in your can be changed in your can be changed in your current situation, current situation, current situation, yes. yes. yes. Yes, that makes sense. Yes. Yes Yes, that makes sense. Yes. Yes , we have a follow-up , we have a follow-up , we have a follow-up on how you on how you on how you separate things that are separate things that are directly related to directly related to the display and, you the display and, you the display and, you know, the engine parts know, the engine parts , right? They specifically , right? They specifically , right? They specifically asked about asked about asked about batch processing, right? batch processing, right? Does the breakdown of Does the breakdown of this work affect the this work affect the this work affect the mechanics, or is mechanics, or is mechanics, or is it related to it related to it related to frame rate, does it frame rate, does it frame rate, does it cause problems cause problems cause problems if you have a weak PC if you have a weak PC if you have a weak PC or a powerful one, how does it or a powerful one, how does it or a powerful one, how does it scale? scale? Okay, and this too, because all Okay, and this too, because all these optimization topics are these optimization topics are these optimization topics are different, so it's different, so it's different, so it's hard to give one hard to give one hard to give one answer, because, answer, because, answer, because, of course, these are different of course, these are different of course, these are different drivers, different situations drivers, different situations , something like that. So when , something like that. So when , something like that. So when I talk about this batch I talk about this batch I talk about this batch processing when processing when processing when updating enemies, I updating enemies, I updating enemies, I mean mean mean mostly what the mostly what the mostly what the player sees, but player sees, but player sees, but that's the end, like, this is the that's the end, like, this is the that's the end, like, this is the completion of our completion of our completion of our work. So, I think, as work. So, I think, as work. So, I think, as I said, this is the I said, this is the I said, this is the ultimate goal, what the ultimate goal, what the ultimate goal, what the player sees.
-
player sees. For example, if you For example, if you see me throwing a see me throwing a see me throwing a grenade like in Call of Duty grenade like in Call of Duty grenade like in Call of Duty and the visuals and the visuals and the visuals get to me, I get to me, I get to me, I can replay it a can replay it a can replay it a frame or two later, frame or two later, frame or two later, buying a little time. buying a little time. The player won't notice The player won't notice that we cheated a little that we cheated a little that we cheated a little , but we'll , but we'll , but we'll buy time. And I buy time. And I buy time. And I like that there is like that there is like that there is no perfect no perfect no perfect option here, because, of course, option here, because, of course, option here, because, of course, there are different computers, there are different computers, there are different computers, different processors, different processors, different processors, different parameters. different parameters. It is difficult to find one It is difficult to find one universal solution universal solution . It is necessary to check . It is necessary to check . It is necessary to check on different machines, on different machines, on different machines, different equipment. different equipment. But sometimes you have to But sometimes you have to think about how to reduce think about how to reduce think about how to reduce the number of frames, the the number of frames, the the number of frames, the frame time, as much as frame time, as much as frame time, as much as possible. And sometimes there is still possible. And sometimes there is still possible. And sometimes there is still no secret no secret no secret recipe for how to recipe for how to recipe for how to satisfy satisfy satisfy both weak and powerful PCs both weak and powerful PCs , because it needs to be , because it needs to be , because it needs to be tested. You need to tested. You need to tested. You need to do something, have a do something, have a do something, have a certain idea. We need to certain idea. We need to certain idea. We need to implement this idea and implement this idea and implement this idea and check the result check the result , right? So Yes , right? So Yes , right? So Yes . I . I . I don't know if I can don't know if I can don't know if I can explain it any better, because that's how explain it any better, because that's how explain it any better, because that's how it works it works it works every day, you know?
-
every day, you know? every day, you know? That's right. I mean That's right. I mean , I think if you're , I think if you're , I think if you're targeting targeting targeting low-end PCs, you want to low-end PCs, you want to low-end PCs, you want to minimize minimize minimize frame times overall, right? Because frame times overall, right? Because frame times overall, right? Because then, you know, you have a then, you know, you have a then, you know, you have a margin, and on a margin, and on a margin, and on a more powerful PC you'll more powerful PC you'll more powerful PC you'll just have just have just have more time to play, more time to play, more time to play, essentially, right? essentially, right? Besides, I gave a Besides, I gave a very simple example, very simple example, very simple example, but we always but we always but we always plan our work this way plan our work this way plan our work this way . You can have . You can have . You can have conditions, for example: I have an conditions, for example: I have an conditions, for example: I have an average frame time average frame time average frame time for such a PC, for such a PC, for such a PC, maybe I can maybe I can maybe I can plan differently plan differently plan differently based on the data based on the data based on the data from the computer, and from the computer, and from the computer, and decide: okay, decide: okay, decide: okay, this this this won't work on this computer. I won't work on this computer. I won't work on this computer. I need to find another need to find another need to find another planning time or something planning time or something planning time or something . So, . So, . So, it's really hard to find it's really hard to find it's really hard to find one "golden" solution one "golden" solution one "golden" solution for this. for this. That's why you're an expert, That's why you're an expert, Conrad. We are very Conrad. We are very Conrad. We are very grateful that you grateful that you grateful that you shared shared shared your knowledge with us. your knowledge with us. your knowledge with us. Yes, thank you for Yes, thank you for Yes, thank you for inviting me. It was really inviting me. It was really inviting me. It was really cool to be able to cool to be able to cool to be able to share this.
Summary
The main theme is optimizing gameplay performance by addressing the "death by a thousand ticks" phenomenon, where many small inefficiencies accumulate to cause problems. Key subjects include performance, gaming tools, optimization, and the concept of a "frame" in game development. The practical takeaway is to identify and fix numerous minor performance bottlenecks rather than focusing on a single large issue to improve overall game responsiveness.