#+title: An Alternative Timer-Based Approach to Game Engine Scheduling In Bevy #+author: Matthew Plant In this article we will be discussing an alternative approach to Bevy's Schedule system that uses timers to encapsulate and schedule game logic, and how this system can be implemented on top of Bevy without any changes. * Background The question of how to implement sequential processes in game engines has a long and storied history. The most basic approach is to use a step function that contains all of the game logic. A typical step function might look as follows: #+begin_src rust struct World { /* ... */ } impl World { pub fn step(&mut self) { collect_input(self); update_positions(self); resolve_collisions(self); other_logic(self); } } #+end_src Effectively, this is how Bevy works. It has a Schedule structure that contains an ordered list of "stages" which are executed one after another. Running all of the stages once completes a "step": #+begin_src rust pub struct Schedule { stages: HashMap>, stage_order: Vec, /* ... */ } impl Schedule { pub fn run_once(&mut self, world: &mut World, resources: &mut Resources) { for name in self.stage_order.iter() { let stage = self.stages.get_mut(name).unwrap(); stage.run(world, resources); } } } #+end_src This is a perfectly acceptable method for structuring games. However, when adding the element of time, this structure becomes less than elegant. Let's consider what Bevy recommends doing if we would like to have a process run every two seconds: #+begin_src rust struct GreetTimer(Timer); fn greet_people( time: Res