unity_mirror_rs/unity_engine/
time.rs

1use once_cell::sync::Lazy;
2use std::sync::atomic::Ordering::SeqCst;
3use std::sync::atomic::{AtomicU16, AtomicU64};
4use std::time::{Duration, Instant};
5
6static mut START_INSTANT: Lazy<Option<Instant>> = Lazy::new(|| None); // 游戏开始时的时间
7static mut FRAME_RATE: AtomicU16 = AtomicU16::new(60); // 60 FPS
8static mut FRAME_COUNT: AtomicU64 = AtomicU64::new(0); // 帧计数器
9static mut FIXED_DATA_TIME: AtomicU64 = AtomicU64::new(20); // 20 ms
10static mut DEFAULT_PING_INTERVAL: f32 = 0.1; // 默认的ping间隔时间(单位:秒)
11static mut PING_WINDOW_SIZE: u32 = 50; // Ping窗口大小
12
13pub struct Time;
14
15#[allow(static_mut_refs)]
16#[allow(unused)]
17impl Time {
18    pub fn start_instant() {
19        unsafe {
20            if START_INSTANT.is_none() {
21                *START_INSTANT = Some(Instant::now())
22            } else {
23                panic!("Time has already started");
24            }
25        }
26    }
27
28    pub fn unscaled_time() -> Instant {
29        unsafe {
30            match *START_INSTANT {
31                None => {
32                    panic!("Time has not started yet");
33                }
34                Some(start_instant) => start_instant,
35            }
36        }
37    }
38    pub fn unscaled_time_duration() -> Duration {
39        Self::unscaled_time().elapsed()
40    }
41
42    pub fn unscaled_time_f64() -> f64 {
43        Self::unscaled_time_duration().as_secs_f64()
44    }
45
46    pub fn frame_add() -> u64 {
47        unsafe { FRAME_COUNT.fetch_add(1, SeqCst) }
48    }
49
50    pub fn get_frame_count() -> u64 {
51        unsafe { FRAME_COUNT.load(SeqCst) }
52    }
53
54    pub fn get_frame_rate() -> f64 {
55        unsafe { 1f64 / FRAME_RATE.load(SeqCst) as f64 }
56    }
57
58    pub fn get_frame_rate_duration() -> Duration {
59        unsafe { Duration::from_secs_f64(1f64 / FRAME_RATE.load(SeqCst) as f64) }
60    }
61
62    pub fn set_frame_rate(frame_rate: u16) {
63        unsafe {
64            FRAME_RATE.store(frame_rate, SeqCst);
65        }
66    }
67
68    pub fn get_fixed_data_time() -> u64 {
69        unsafe { FIXED_DATA_TIME.load(SeqCst) }
70    }
71
72    pub fn get_fixed_data_time_duration() -> Duration {
73        unsafe { Duration::from_millis(FIXED_DATA_TIME.load(SeqCst)) }
74    }
75
76    pub fn set_fixed_data_time(fixed_data_time_millis: u64) {
77        unsafe {
78            FIXED_DATA_TIME.store(fixed_data_time_millis, SeqCst);
79        }
80    }
81
82    pub fn get_min_interval() -> Duration {
83        unsafe {
84            let fixed_data_time_millis = Self::get_fixed_data_time();
85            let frame_rate_duration = Self::get_frame_rate_duration().as_millis() as u64;
86            Duration::from_millis(u64::min(fixed_data_time_millis, frame_rate_duration))
87        }
88    }
89
90    pub fn ping_interval() -> f64 {
91        unsafe { DEFAULT_PING_INTERVAL as f64 }
92    }
93    pub fn get_ping_window_size() -> u32 {
94        unsafe { PING_WINDOW_SIZE }
95    }
96}
97
98#[derive(Debug, Copy, Clone, Default)]
99pub struct ExponentialMovingAverage {
100    alpha: f64,
101    initialized: bool,
102    pub value: f64,
103    pub variance: f64,
104    pub standard_deviation: f64,
105}
106
107impl ExponentialMovingAverage {
108    pub fn new(n: u32) -> Self {
109        Self {
110            alpha: 2.0 / (n as f64 + 1.0),
111            value: 0.0,
112            variance: 0.0,
113            standard_deviation: 0.0,
114            initialized: false,
115        }
116    }
117
118    pub fn add(&mut self, new_value: f64) {
119        if self.initialized {
120            let delta = new_value - self.value;
121            self.value += self.alpha * delta;
122            self.variance = (1.0 - self.alpha) * (self.variance + self.alpha * delta.powi(2));
123            self.standard_deviation = self.variance.sqrt();
124        } else {
125            self.value = new_value;
126            self.initialized = true;
127        }
128    }
129
130    pub fn reset(&mut self) {
131        self.value = 0.0;
132        self.variance = 0.0;
133        self.standard_deviation = 0.0;
134        self.initialized = false;
135    }
136}