@@ -5,6 +5,60 @@ use bevy_reflect::{FromReflect, Reflect};
5
5
use crate :: time:: Time ;
6
6
use crate :: real:: Real ;
7
7
8
+ /// The virtual game clock representing game time.
9
+ ///
10
+ /// Normally used as `Time<Virtual>`. It is automatically inserted as a resource
11
+ /// by `TimePlugin` and updated based on `Time<Real>`. The virtual clock is
12
+ /// automatically set as the default generic `Time` resource for the update.
13
+ ///
14
+ /// Virtual clock differs from real time clock in that it can be paused, sped up
15
+ /// and slowed down. It also limits the amount it will move forward based on a
16
+ /// single update, to prevent bugs and bad behaviour in game logic if the
17
+ /// updates do not always come at regular intervals.
18
+ ///
19
+ /// The virtual clock can be paused by calling `pause()` and unpaused by calling
20
+ /// `unpause()`. When the game clock is paused `delta()` will be zero on each
21
+ /// update, and `elapsed()` will not grow. `effective_relative_speed()` will
22
+ /// return `0.0`. Calling `pause()` will not affect value the `delta()` value
23
+ /// for the update currently being processed.
24
+ ///
25
+ /// The speed of the virtual clock can be changed by calling
26
+ /// `set_relative_speed()`. A value of `2.0` means that virtual clock should
27
+ /// advance twice as fast as real time, meaning that `delta()` values will be
28
+ /// double of what `Time<Real>::delta()` reports and `elapsed()` will go twice
29
+ /// as fast as `Time<Real>::elapsed()`. Calling `set_relative_speed()` will not
30
+ /// affect the `delta()` value for the update currently being processed.
31
+ ///
32
+ /// The maximum amount of delta time that can be added by a single update can be
33
+ /// set by `set_max_delta()`. This value serves a dual purpose in the virtual
34
+ /// clock.
35
+ ///
36
+ /// If the game temporarily freezes due to any reason, such as disk access, a
37
+ /// blocking system call, or operating system level suspend, reporting the full
38
+ /// elapsed delta time is likely to cause bugs in game logic. Usually if a
39
+ /// laptop is suspended for an hour, it doesn't make sense to try to simulate
40
+ /// the game logic for the elapsed hour when resuming. Instead it is better to
41
+ /// lose the extra time and pretend a shorter duration of time passed. Setting
42
+ /// `max_delta` to a relatively short time means that the impact on game logic
43
+ /// will be minimal.
44
+ ///
45
+ /// If the game lags for some reason, meaning that it will take a longer time to
46
+ /// compute a frame than the real time that passes during the computation, then
47
+ /// we would fall behind in processing virtual time. If this situation persists,
48
+ /// and computing a frame takes longer depending on how much virtual time has
49
+ /// passed, the game would enter a "death spiral" where computing each frame
50
+ /// takes longer and longer and the game will appear to freeze. By limiting the
51
+ /// maximum time that can be added at once, we also limit the amount of virtual
52
+ /// time the game needs to compute for each frame. This means that the game will
53
+ /// run slow, and it will run slower than real time, but it will not freeze and
54
+ /// it will recover as soon as computation becomes fast again.
55
+ ///
56
+ /// You should set `max_delta()` to a value that is approximately the minimum
57
+ /// FPS your game should have even if heavily lagged for a moment. The actual
58
+ /// FPS when lagged will be somewhat lower than this, depending on how much more
59
+ /// time it takes to compute a frame compared to real time. You should also
60
+ /// consider how stable your FPS is, as the limit will also dictate how big of
61
+ /// an FPS drop you can accept without losing time and falling behind real time.
8
62
#[ derive( Debug , Copy , Clone , Reflect , FromReflect ) ]
9
63
pub struct Virtual {
10
64
max_delta : Duration ,
@@ -13,26 +67,41 @@ pub struct Virtual {
13
67
}
14
68
15
69
impl Time < Virtual > {
16
- /// Default max_delta value.
17
70
const DEFAULT_MAX_DELTA : Duration = Duration :: from_millis ( 333 ) ; // XXX: better value
18
71
19
- /// Returns the maximum amount of time that can be added to the clock by a
72
+ /// Returns the maximum amount of time that can be added to this clock by a
20
73
/// single update, as [`std::time::Duration`].
21
74
///
22
75
/// This is the maximum value [`Self::delta()`] will return and also to
23
- /// maximum time [`Self::elapsed()`] will be increased by in a single update.
76
+ /// maximum time [`Self::elapsed()`] will be increased by in a single
77
+ /// update.
78
+ ///
79
+ /// This ensures that even if there are no updates scheduled for an extended
80
+ /// amount of time, there won't be a huge update at once for the clock. This
81
+ /// also limits the number of fixed time ticks that will be evaluated at
82
+ /// maximum per a single update.
83
+ ///
84
+ /// The default value is [`Self::DEFAULT_MAX_DELTA`].
24
85
#[ inline]
25
86
pub fn max_delta ( & self ) -> Duration {
26
87
self . context ( ) . max_delta
27
88
}
28
89
29
- /// Sets the maximum amount of time that can be added to the clock by a
90
+ /// Sets the maximum amount of time that can be added to this clock by a
30
91
/// single update, as [`std::time::Duration`].
31
92
///
32
- /// This ensures that even if there are no updates scheduled for an extended
33
- /// amount of time, there won't be a huge update at once for the clock. This
34
- /// also limits the number of fixed time ticks that will be evaluated at
35
- /// maximum per a single update.
93
+ /// This is the maximum value [`Self::delta()`] will return and also to
94
+ /// maximum time [`Self::elapsed()`] will be increased by in a single
95
+ /// update.
96
+ ///
97
+ /// This is used to ensure that even if the game freezes for a few seconds,
98
+ /// or is suspended for hours or even days, the virtual clock doesn't
99
+ /// suddenly jump forward for that full amount, which would likely cause
100
+ /// gameplay bugs or having to suddenly simulate all the intervening time.
101
+ ///
102
+ /// re are no updates scheduled for an extended amount of time, there won't
103
+ /// be a huge update at once for the clock. This also limits the number of
104
+ /// fixed time ticks that will be evaluated at maximum per a single update.
36
105
///
37
106
/// The default value is [`Self::DEFAULT_MAX_DELTA`]. If you want to disable
38
107
/// this feature, set the value to [`std::time::Duration::MAX`]
0 commit comments