Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The CurrentTime property returns how much time has passed since the start of the game's execution in seconds. This value changes every frame - specifically when calling FlatRedBallServices.Update. This value will only change whenever FlatRedBallServices.Update, meaning it will be the same value throughout the entire frame. Therefore, this value can be used to uniquely identify a frame.
CurrentTime advances according to TimeFactor, which defaults to 1. If TimeFactor is greater than 1, then CurrentTime advances more quickly. If TimeFactor is less than 1, CurrentTime advances more slowly.
CurrentTime is not affected by pausing the game. If a screen is paused, CurrentTime still advances normally every frame.
The TimeManager provides functionality for measuring differences in time. The TimeManager can be used to tell how much time has passed since an event has occurred, how much time is left before a predetermined event will occur, how much time the last frame took to process and render, and to profile code performance.
For information on how long a frame has taken, see the SecondDifference page.
The TimeManager.ScreenCurrentTime returns the number of seconds since the current screen was created. This value can be used to find the amount of time that has passed since an event has occurred, or mark the time for when an event should occur. The following code shows how to check how long it has been since an Entity has been created and then makes the CircleInstance within the entity invisible after five seconds.
The TimeManager provides 3 times:
CurrentScreenTime
CurrentTime (also known as game time)
CurrentSystemTime
If you are writing code for game play, such as timing bullet shots or enemy spawns, you should use CurrentScreenTime and CurrentScreenSecondsSince. Since most of the timing code in a game is game play related, you will usually use these values. For a deeper understanding let's look at how the three values differ
CurrentScreenTime reports the number of seconds since the current screen has started. The value reported by CurrentScreenTime will remain the same throughout a frame. This means it will be the same in any CustomActivity until the frame ends. This time is impacted by TimeManager.TimeFactor and will not increment if the current screen is paused. This value resets back to 0 when moving to a new Screen.
CurrentTime, also known as game time, reports the number of seconds since the game has started. Like CurrentScreenTime, this value will also remain the same throughout the current frame. This time is impacted by TimeManager.TimeFactor. It will continue to increment when a screen is paused, and it will never reset back to 0 unless a game is completely stopped and restarted. Since this value does not pause when a screen is paused, it can be used to uniquely identify a frame.
CurrentSystemTime reports the number of seconds since the game has started. Unlike CurrentTime, this value will continually change throughout a frame, and it is not impacted by TimeManager.TimeFactor. This time is real world time.
MonoGame provides a GameTime reference in the Game's Update and Draw methods, so question of which to use may arise - GameTime or the TimeManager? The TimeManager's CurrentTime is equal to the Game's TotalGameTime.TotalSeconds property so in Update they can be used interchangeably. Since the TimeManager is always in scope it is recommended for consistency to use this instead of passing references to the GameTime. [subpages depth="1"]
The SumTimeSection method can be used to time sections that may get repeated over and over. The regular TimeSection method will add a new section any time the TimeSection method is called. The SumTimeSection will combine duplicate labels, meaning it can be used inside a loop, or over the span of multiple frames. For more information on profiling with SumTimeSection, see this page.
TimeFactor is a property which can be used to make time run slower or faster. By default TimeFactor is set to 1, meaning time runs regularly. A value of 2 will make time run twice as fast.
Changing TimeFactor affects the following properties:
SecondDifference - Increasing the TimeFactor increases SecondDifference. In other words, if TimeFactor is set to 2, then the game runs twice as fast, so the amount of time each frame is twice as long.
CurrentTime - Increasing TimeFactor makes CurrentTime increase faster. In other words, if TimeFactor is set to 2, then CurrentTime advances twice as fast.
CurrentScreenTime - Increasing TimeFactor makes CurrentScreenTime increase faster, similar to CurrentTime.
The following code will make time run twice as fast:
The following code will make the game run at half the speed (slow motion):
The SecondsSince method can be used to detect how many seconds have passed since a given time. This method is often used in combination with the CurrentTime property.
Note that SecondsSince assumes that the value passed is in game time (using TimeManager.CurrentTime
) and not screen time ( TimeManager.CurrentScreenTime
). This method is rarely. It is only needed if the amount of in-game time that has passed is greater than some value which may span mulitple screens.
Note that this operation assumes that ability cooldown should persist between screens. If your game has abilities which cool down, but which reset when a screen changes (such as the player re-starting a level), then CurrentScreenSecondsSince should be used. However, if you would like cooldown to persist between multiple screens, you can use SecondsSince as shown in the following code:
The SystemCurrentTime property reports the system's current time right when the method is called. This differs from the CurrentTime property because the CurrentTime property will not change during a frame; however, the SystemCurrentTime will always be changing continually. For example, consider the following code:
The code above may produce the results showin the table below. The systemCurrentTime values would be different for every call, while DoSomeStuff would always be the same:
These timing values have no meaning - they were picked purely as an example.
If you've ever wondered how long a piece of code takes to run, then the SystemCurrentTime is a great way to measure it. To profile a piece of code, get the SystemCurrentTime before and after the code. For example, if you wanted to measure a method called PerformCollisions you might do something like this:
Of course, keep in mind that:
This method is not 100% accurate - it's only as accurate as the system timer it relies on. Measuring something that is very fast, like the allocation of a variable, will likely not give you much information.
This method may result in a method call. Method calls can be slow, so again, if you are measuring something very fast, you may not get very accurate information.
In general, this timing becomes more accurate the longer you spend between calls. Once you reach one millisecond (.001) or greater, your results should be fairly accurate.
The TimeManager returns all of its time in seconds. If you are working with code that accepts TimeSpans, then you may need to create a new TimeSpan from the TimeManager's properties. The following code creates a TimeSpan that marks how much time has passed since last frame:
If you are working on a game which requires actions to be performed at a particular time, you may be inclined to implement an accumulation or decrementing implementation for your timing. In other words, if you want something to happen in 5 seconds, you might write code as follows:
If you are interested in performing a particular task at a certain time - such as setting a property or calling a method, you may want to look at some of the classes in the FlatRedBall.Instructions namespace. Specifically:
FlatRedBall.Instructions.IInstructable
FlatRedBall.Instructions.Instruction
FlatRedBall.Instructions.InstructionManager
FlatRedBall.Instructions.MethodInstruction
However, you may still want to perform an action at a certain time without the use of instructions.
The proper way is to store a value and use that value in all of your comparisons. For example:
It is improper to accumulate a value and test that against a time:
Similarly, it is improper to store a value to decrement the value every frame and test against 0. The reason is because you'll get more accurate results if you only perform an operation once (timeToExecute = TimeManager.CurrentTime + 5) instead of multiple times (timeThatHasPassed += TimeManager.SecondDifference).
The proper way to do this is to calculate every value based off of an initial time rather than off of the previous time. For example, consider a situation where you have a period of time that you want to subdivide into twenty events. The incrementing should be done at an integer level to avoid accumulation error.
It is improper to calculate the amount of time that you should divide by outside of the loop and increment by that value:
The second method might seem like a better way to mark the times because it only requires one division, making it appear like it's superior from an performance point of view. Whether this is true or not doesn't really matter because this code is very error prone. Not only will values which fall later in the divisionTimes array be less accurate because of the numerous += operations performed on a double, but it's also possible to have an out-of-bounds error in the improper code if the values happen to be rounded down and a 21st value is added in the array. It's far more accurate to increment integers then perform a division only one time per divisionTimes value.
The CurrentScreenSecondsSince method returns how many seconds have passed since the argument time according to the current screen time. This is the preferred method of detecting how long time has passed since it takes into consideration screen pausing and the TimeManager's TimeFactor property.
The following code can be used to create an enemy once every 5 seconds.
While there are a number of ways to profile your game to improve its performance, one of the simplest (and often very effective) ways to do this is to simply measure the amount of time code takes to run. The TimeManager provides methods which can be helpful in accomplishing this. Note that measuring code using the TimeManager is considered a *low level* form of profiling your game.
The TimeManager provides accurate, low-level timing which can be used for profiling your code. The TimeSection methods both times and records the results of the timing. The information recorded through TimeSection can be retrieved through GetTimedSection. The following code creates 280 Sprites and performs a brute-force all vs. all Move collision. This inefficient method is so that the code takes a significant amount of time to execute.
Add the following at class scope:
Add the following in Initialize after initializing FlatRedBall:
Use the following in Update method (entire method shown):
TimeSections are a great way to measure how much time has passed between two pieces of code. TimeSection calls can follow one after another to measure multiple sections of code; however, there is one area where TimeSection is not very effective. Consider the following example:
Assume that the above code is called every frame, and based off of a TimeSection that is "wrapping" the above block of code you determine that this piece of code is what is greatly slowing your project down. The problem is you don't know which part is actually slowing things down. Sure, you could guess, but that's not what profiling is all about! And if you put TimeSection calls after every call in the loop, you'd end up with a lot of TimeSections; 3 * mEntities.Count to be exact. This information would not be very helpful. To identify which of the three calls is taking up the most time, you can use the "sum" timing methods available in the TimeManager. The general pattern is:
The methods work essentially the same as TimeSection calls except that sum sections with the same name are added together. For example, the above code would be modified as follows to get the time each section took:
Result would have 3 entries - each would report how much time has been spent inside each of the methods. Again, keep this in mind whenever timing pieces of code that fall inside of a loop - even if your loop is outside of the method where your timing methods lie. However be sure to put your StartSumTiming call outside of any loops or else your information on previous loops may get overwritten!
In many situations you will find that a relatively small number of areas of code take up the majority of your frame time. Using the TimeManager methods can help you track down which areas of code are taking the most amount of time. A common approach is to measure time at a very high level, then dive deeper once you find which method is causing problems. For example, consider a situation where a Screen is slowing down your game. You may want to do do initial tests as shown above to determine if the show-down is occurring in the Draw calls or in the Update calls. We'll assume that you have done this and you've determined that the Update calls are very slow and you think they could be improved. Since you know the slow-down is in Update, and you also know the Screen that is causing the slow-down, you would be able to see which method in the Screen's CustomActivity is causing problems. For example, your code may look like:
One of the benefits of keeping logic out of your Activity class is it can help you isolate performance problems very quickly:
This kind of diagnostic will often give you a very clear indication of where the problem lies. For example, you may find that 95% of the time spent in activity is in just one of those functions. If this is the case, then it is clear that you should remove or comment out the TimeSection calls shown above, navigate to the method that took the most time, and divide that up with TimeSection calls.
We generally recommend not implementing this type of solution in your code because it can lead to timing bugs due to the inaccuracy of numerical operations. Also, this makes your code a little less flexible for additional functionality such as . Whenever possible we recommend reducing the number of operations it takes to get to a particular value by using base time values and using those in operations. To clarify, this article will present a number of common scenarios, then show the proper way to achieve the desired functionality. For comparison, we'll also show an improper way of implementing the desired functionality.
If you are using Glue, then the Screen class has a lot of timing and pausing functionality built in. See for a current time value that can be used which considers paused time.
You may want to perform an action at a given interval, or according to some value set in data. If you are going to store these values in an array of doubles or , you may need to calculate these values up front.
Call # | curentTime | systemCurrentTime |
1 | 42 | 42.001 |
2 | 42 | 42.0023555 |
3 | 42 | 42.005431 |
The SecondDifference property returns the amount of time that has passed since the last frame. This value is updated only once per frame, and will remain the same value throughout an entire frame. This value can be used to manually update a value (such as an object's position) according to time (as opposed to frames).
The following code shows how to adjust the position of an object so that it moves at 100 pixels per second.
You can use the SecondDifference property to measure how long a frame has taken. This information can be used to get how many frames per second your game is running at. To do this:
When first considering how to move objects in your game, you may realize that the Update method is called every frame. Therefore, making small changes every time Update looks like a good way to move your objects. This may or may not be true depending on your implementation. One method that is often seen as the most obvious way to gradually change the value of an object is to increase or decrease it by some value as follows:
While the code is very simple, there is one main problem - it's tied to framerate. The FlatRedBall XNA template does by default run at a set framerate; however, you may at any time decide to change this framerate, or even turn off fixed framerate calculations fo a number of reasons. If you end up doing this, your objects will all of a sudden start to run at different speeds. Furthermore, this speed may fluctuate depending on the resources available to your computer, and can vary greatly when running your game on different machines. As mentioned in the section above, accurate time based movement can be accomplished using the SecondDifference value:
Using velocity and rate values can help reduce object management and keeps code cleaner.
Note that if you are working with Entities, you can also the to achieve the same result.
The default behavior of FRB is to attempt to force a certain frame rate. Keep in mind that by default FRB attempts to keep framerate at 60 fps so you will want to disable fixed framerate to get more accurate performance numbers. For more information see the . If your game is running slowly, or if you have very long frames (such as when the game first starts, or when transitioning between screens) frame time may be longer.
The TimeManager.SecondDifference returns the amount of time that the last frame took to process and render - or more specifically the second difference between the start of the current frame and the start of the last frame. This can be used to apply time based movement to objects. Keep in mind that this is usually not necessary as most are associated with managers which automatically apply velocity to position. For information on turning off the fixed time step, see the wiki entry. The following code manually applies a velocity to a .
This is better because it resolves the issue of being dependent on frame time, and in some cases this is the best or only solution to moving objects. However, the (and objects which inherit from it) expose velocity and rate values for many properties including position and rotation. Other objects include velocity and rate values for scale and color component values. For example, the above code to move an object by 1 unit per second can also be accomplished as follows: