Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Manually updated objects are objects which are removed from the FlatRedBall engine's automatic managed lists. In other words, manually updated objects will not have behavior such as velocity or attachments automatically applied. The following set of articles discuss what automatic vs. manual udpates are and why they are important for performance.
So you're working on a FlatRedBall game and you're having performance problems? Don't worry, it happens to almost everyone. Performance issues can happen at any point throughout the development process. Fortunately, many methods exist for diagnosing. If you're having any problems with performance, or if you'd like to take some preventative measures in making sure your game runs quickly, then this is a great place to start.
The first step in solving performance problems is to identify which type of performance problem you're having. Let's look at the most common:
My game takes a long time to load
My game runs smoothly, but then seems to freeze or drop frames every once in a while
My game constantly runs slowly in a particular situation (such as in a particular level, or when lots of enemies are on screen)
Let's look at each one individually and explain what may be happening:
If your game takes a long time to load, it may be one of the following:
If your game takes a long time to load before anything shows on-screen, then it may be related to how much content is in your Global Content Files. <under construction>
If your game loads fine initially, but it takes a long time to transition between screens then your screen may suffer from either long load times or a long CustomInitialize function. For more information, see this page.
If your game seems to run slow, but the slowdown is no consistent then it is likely that you are experiencing slowdown from the garbage collector. Visual Studio offers a tool for measuring memory allocation. For more information, see the Visual Studio documentation for analyzing memory usage: https://learn.microsoft.com/en-us/visualstudio/profiling/dotnet-alloc-tool?view=vs-2022
If your game is constantly running slowly, the reason may be one of the following:
Number of objects in the engine. This one is fairly easy to diagnose. We can find out if the problem is related to the number of objects in your engine simply by asking the engine to tell us how many objects it is managing. To identify if this is the problem, you should start with teh Profiling tab in the FlatRedBall Editor. For more information, see the Profiling tab page.
Complicated logic in Custom code. This means that your CustomActivity code is causing problems. It could be in your Screen or it could be in your entities. For information on detecting and fixing complicated logic in custom code, see this link
Rendering issues. This means that you have too many graphical objects on screen. This is possible, however it is not as common of a problem as the first two, so you should look here only after you have eliminated the first two options. For information on detecting and fixing complicated logic in custom code, see this link
Rendering (the process of displaying graphics on screen) can be a source of performance problems. If you're not familiar with rendering you may ask "Why do we differentiate between rendering and other areas of code which may slow performance?" A few reasons for this are:
Computers often have dedicated hardware for rendering.
Rendering is often "async". In other words, a particular call may begin the process of rendering, and the code flow can continue while the rendering happens in the background. While this means that rendering can be fast, it also means that it can be difficult to measure exactly where the slowdown occurs.
Rendering is often handled internally by FlatRedBall, so unless you are building against source you may not know exactly what is happening in the rendering code.
Special software exists to help diagnose rendering problems.
Rendering slowdowns can occur due to a number of problems:
Render State changes - for more information see FlatRedBallXna:Tutorials:Render_State_Changes
Fill rate/vertex count - for more information see the PIX page
If you have a screen which seems to take a long time to load then this can be the cause of either long load times in generated code or a slow CustomInitialize function. The first step in fixing the problem is to identify whether it is custom or generated code.
CustomInitialize can be measured easily by using the TimeManager's SystemCurrentTime property along with the Debugger's CommandLineWrite function. For this example, let's assume a simple CustomInitialize which looks like this:
The actual contents of CustomInitialize don't really matter - this is just some sample code that we can use to show how to measure CustomInitialize time. To measure and output the time, we'll need to do 3 things:
Record the current time at the start of the function
Record the current time at the end of the function
Print out how long the initialize took by subtracting the beginning time from the end time
CustomInitialize can be modified to do this as follows:
The example above tells us how long CustomInitialize takes, but it doesn't tell us how long generated code took to execute. This is important if your CustomInitialize code is fast (like less than 1 second) but the Screen still takes a long time to load. We can ask Glue to give us more detailed information to solve this. The steps to solve this are:
Turning on detailed performance logging in Glue
Modifying your code to output load times
To do this:
Switch to glue
Select "Settings"->"Performance Settings"
Set "RecordInitializeSegments" to "True"
Click "Done"
Now Glue will generate code to measure Screen initialization time. Next we'll output this information on-screen.
To do this:
Switch to Visual Studio
Open your Screen that you want to measure the initialization times on
Go to CustomActivity (not CustomInitialize)
Add the following code in CustomActivity:
So far we've discussed how to measure where slowdowns are occurring.
If the slowdown is in CustomLoadStaticContent or LoadStaticContent (notice the name of your screen will be prefixed), then you can solve the problem either by loading less content or by using a loading screen. For more information on using loading screens, see this page.
This section discusses CustomActivity and its potential impact on performance. Although CustomActivity can have an impact on performance, more often than not performance problems are a result of having too many managed objects in the engine. Therefore, you should always check this first before looking at your custom code for performance problems. For information on checking the number of objects, see this link.
If your game runs slow because of your code, this could be code which is located in a variety of places in custom code. It may not actually be part of the CustomActivity of your screen because the slowdown could be in an entity, event handler, async method, or instruction. Therefore, finding your slowdown may not be a simple matter of adding timing code around your Screen's CustomActivity. Visual Studio offers a powerful profiler which can be used to measure where your game's slowdown occurs.
Your game may be experiencing performance problems only in a particular screen or a particular situation. Therefore, you will want to have your game in the "slow" state before beginning profiling so that the profiler returns the most relevant information. Once you have this situation set up, place a breakpoint at the beginning of your Screen's CustomActivity method. Once your game hits the breakpoint, open Debug -> Windows -> Show Diagnostic Tools
Enable CPU profiling. Remove the breakpoint. Run your game. After enough time has passed, re-add the breakpoint. Once you hit this breakpoint, Visual Studio should show you which code is responsible for time spent since you started profiling.
Your game should now output information about initialization time: Notice that this output method uses exponential notation for very small values. For example in the image above GameScreenPooled PostInitialize took "4E-07". This is the equivalent of 4 * 10^(-7), or in other words 0.0000004. Typically if you see exponential notation you are dealing with time values which are so small that they will not have much if any of an impact on performance, so they can be treated as if they're 0. If the output from ToStringVerbose is too large to view on screen you can also output this to the Visual Studio output window as follows:
Even if you've used FlatRedBall for a while you may not be familiar with exactly what a "manually updated" object is. The reason for this is because the option to make things manually updated exists almost exclusively for performance reasons. Technically one might want to manually update objects to achieve custom behavior as well, but generally this is not encouraged because it can lead to bugs and often this type of implementation duplicates functionality already present in automatically updated objects. In short, you can designate objects as manually updated to make your game run faster, and that's usually the only reason this is done.
To answer the question of what a manually updated object is, let's look at a very common piece of code:
If you've used FlatRedBall you probably know that the code above will create a Sprite, then start the Sprite's movement to the right at 5 units per second. As mentioned in one of the introductory tutorials, the Velocity property changes the Position property based off of elapsed time. This is done "automatically". This "automatic" application of velocity is what it means to be "automatically updated". So, then you might be guessing that something which is manually updated does not have Velocity applied to it every frame - and if so you're right! If an object is manually updated, then it means that the FlatRedBall Engine is not performing every-frame automatic updates on it.
The following is a list of properties which are applied for automatically updated objects. Not all properties apply to every automatically updated object. For example, the ScaleXVelocity property doesn't apply to Scale on the PositionedObject class because the PositionedObject class doesn't have the ScaleX or ScaleXVelocity properties. However, looking below can give you an idea of what kind of things are done for you by the engine:
Property that modifies
Modified property
Notes
Velocity
Position
Acceleration
Velocity/Position
Position
RotationXVelocity/RotationYVelocity/ RotationZVelocity
RotationX/RotationY/RotationZ RotationMatrix
Drag
Velocity
RelativeVelocity
RelativePosition
RelativeAcceleration
RelativeVelocity/RelativePosition
RelativeRotationXVelocity RelativeRotationYVelocity RelativeRotationZVelocity
RelativeRotationX/RelativeRotationY/ RelativeRotationZ/ RelativeRotationMatrix
Relative values
Matching absolute values
If Parent is not null.
AnimationSpeed/CurrentChain
CurrentChainIndex/Texture/Texture coordinates
ScaleXVelocity/ScaleYVelocity
ScaleX/ScaleY
Instructions
Potentially anything
The engine calls Instructions on any IInstructable that it manages.
RedRate/GreenRate/BlueRate/ AlphaRate
Red/Green/Blue/Alpha
So, if you have a group of objects which do not have any of the above properties then that group of objects is a good candidate for being made manually updated. That is, an object can safely be made manually updated if it doesn't have:
Movement
Color rate changes
Attachments
Scale velocities
Animations
Instructions
The answer is "it depends". It depends on how much of your game time is actually spent on updates. Converting to manually updated helps the most when your game has a large number of objects (such as Sprites or PositionedModels) which are going to be static - such as part of a level. It's common to have games which have hundreds or even thousands of such objects - most of which aren't even on screen. In these situations the engine may be spending a considerable amount of time updating these objects unnecessarily. Grabbing a reference to these objects (perhaps through some naming convention if using Scenes) and converting them to be manually updated can greatly improve performance. The process is fairly straight-forward so if you suspect that you may be experiencing update-related performance issues, give it a try. For an example of how this works in a very simple scenario, see the SpriteManager's AddManualSprite wiki entry.
Automatic updates can take a significant amount of time every frame if your game includes a large number of automatically updated objects. The first step in improving the performance of your game is measure the number of objects your game contains. This article will discuss how to do this.
This article assumes that you already have a working project in FlatRedBall - preferably one with a variety of automatically updated objects (Sprites, Shapes, Entities, Text objects, etc).
The FlatRedBall Engine includes a class called which can help you debug and diagnose problems in your project. In this case we'll be using a function called WriteAutomaticallyUpdatedObjectInformation. This method will print the number of managed objects to the screen in real time. It's a very simple method to use which provides a lot of useful information. To use it:
Open your project in Visual Studio
Navigate to your Game class (which is by default called Game1 in Game1.cs)
Navigate to the Update method
Add the following code *after* FlatRedBallServices.Update:
Run your game
Now you should see information about the objects that are present in your game. The top-left of your screen may look similar to:
The information printed out gives you an idea of what the engine is spending its time updating. In the picture above you can see that the game has a total of 50 automatically updated objects. The lines show the breakdown - the majority of the objects are Sprites, then PositionedObjects (which are usually Entities if using Glue) make up the second largest category.
This question can be difficult to answer. The short answer is "it depends". Here are some considerations to keep in mind when working on a game:
Numbers greater than 1000 are usually bad.
Games with fewer than 100 are unlikely to have performance problems from managed objects.
Platforms without as much processing power (such as mobile platforms) can have performance problems with as few as 500 managed objects.
Fewer objects is always better on mobile platforms even if no performance problems are visible. Fewer objects means less processing needed per-frame, which means your game won't run down batteries as quickly.
For the most part the cost of each type of object is equal. In other words, managing one Text takes just as much time as managing one Sprite. Therefore, when looking to improve the performance of your game, you likely want to tackle the largest number first.
If is true.
Position/
If is true.
If you are using Glue then it's likely that a large number of your automatically updated PositionedObjects are Entities. For more information on making these manually updated, see the .
For information on how to improve the performance of your game if it has a large number of Sprites, see .
Particles may require a large number of FlatRedBall Sprite instances. This guide shows how to create an incredibly efficient particle system using manual particle sprites.
Manual sprites are sprites which the engine does not automatically update every frame. Manual sprites are an efficient alternative to automatically-updates sprites (the default) if:
The sprite does not change often (such as a static background object)
The sprite changes frequently, but only uses a subset of variables that change every frame
The term "particle sprite" implies it is used for particle effects, but technically a particle sprite is pooled - supporting rapid addition and removal without any memory allocation.
The following code is written in a screen which has access to a Texture2D called Texture. Notice that it creates sprites very quickly (60 per second), and even at large numbers the game will run at a reasonable speed:
This section will walk you through identifying how many Sprites you have in your game, and how you can reduce this number to improve performance. If you haven't yet, you should first read the article about measuring all PositionedObjects. This article can be found here.
If you've used WriteAutomaticallyUpdatedObjectInformation and have identified that Sprites are causing performance issues, then the next step is to figure out where your Sprites are coming from. Of course, if your game is simple, or if your Sprites do not come from diverse sources, then you may already know where your Sprites are coming from. For example, if you have a level with a very large Scene (.scnx file) then it's likely that many of your Sprites are coming from this file. However, let's assume that you're not sure where your Sprites are coming from.
Just like in the general PositionedObject measuring tutorial, the FlatRedBall Debugger provides functions that can help us identify where our Sprites are coming from. To use this function:
Open your project in Visual Studio
Navigate to your Game class (which is by default called Game1 in Game1.cs)
Navigate to the Update method
Add the following code *after* FlatRedBallServices.Update:
Run your game
Here is an example of what output might look like:
The image shown above was taken from Baron when it was late in its development. At this point a considerable amount of optimization had already been performed. The first line tells us the total number of Sprites which are automatically updated by the engine. In this case, the engine is managing 111 Sprites. Assuming you want to reduce this number, the next step is to identify where all of your Sprites are being used. What follows are lines indicating how many Sprites are being used by which entity, or marked as Unparented if the Sprites are not associated with any entities. For example, we can see that in this screen shot 51 of the Sprites are being used in the OverworldLevel entity. This represents almost half of our updated Sprites. If we were to try to reduce the number of Sprites here, then OverworldLevel would be a good place to start.