#Fixed update not working

85 messages ยท Page 1 of 1 (latest)

quiet cairn
#

ok so last week i asked in #general about why my game randomly doubled in tick/frame rate, player and animations moved twice as fast, etc.

It was because i was setting up my fixed time/update stuff wrong.

However today i found 2 new pieces of info:

  1. it doesnt work ๐Ÿ˜›

  2. macOS seems to optimize something while plugged into a power source vs not plugged in, because as SOON as i plug in, i get the double speed symptoms, and when i plug out, i go back to "normal" or expected behaviour. Weird, but cool

my set up for fixed updates is:

pub const TIME_STEP: f32 = 1.0 / 60.0;

#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
pub enum CoreGameSet {
    Main,
}

app.edit_schedule(CoreSchedule::FixedUpdate, |s| {
   s.configure_set(CoreGameSet::Main.run_if(in_state(GameState::Main)));
 })
  .insert_resource(FixedTime::new_from_secs(TIME_STEP));

//in my input system
app.add_systems(
              (
                  Self::move_player,
                  ... other systems
              )
                .in_base_set(CoreGameSet::Main),
      )

Im not sure what else i need to do and why this isnt working lol

strong bough
#

You're adding the set to the fixed update schedule but adding them to the default schedule? ๐Ÿค”

#

As for the framerate thing, maybe vsync is on and it changes the screen changes refreshrate? Or if no vsync it might just be throttled performance on battery (lower clock speed do drop power draw by much more than the clock speed dropped after all)

quiet cairn
strong bough
#

Ah, allright. I can explain it to you, I also ran into issues like this at the start

quiet cairn
quiet cairn
strong bough
#

So every schedule has their own configuration of sets, and you add systems to schedules

#

The default schedule is Main I think, which contains base sets for First, PreUpdate, StateTransition, the part that runs FixedUpdate, Update, PostUpdate, and Last ...

#

But FixedUpdate is a different schedule so not only do you have to specify you want to add your systems to that schedule, you also need to define how you want the normal sets to work (tho you can set them up with default ordering, which I don't really recommend)

#

Since you do configure your set in the FixedUpdate schedule already, what you need here is most likely just a .in_schedule(CoreSchedule::FixedUpdate)

quiet cairn
#

also fyi i added the struct def for CoreGameSet as well, since i wasnt sure what #[system_set(base)], it seems wrong?

#

This makes a bit more sense, I think the part im missing is... what is a Set? when you say you add systems to schedules, am i adding them to a particular set within that schedule?

strong bough
#

Yea you don't need to add the base set part. Base sets are mostly just there for backwards compatability, they're already gone in bevy main too

quiet cairn
#

so in theory what i did was configure the FixedUpdate schedule, add my set to it, but tell that set to run in the base Main schedule?

strong bough
#

Yes, and since the set probably wasn't configured in Main, it will just act like they aren't in a set

quiet cairn
#

huh, that seems like a weirdly easy footgun

strong bough
#

Yes, that's why bevy main already removed it ๐Ÿ˜‚

quiet cairn
#

wait they removed the base set part, or the need for .in_schedule(CoreSchedule::FixedUpdate)

#

or i guess both?

strong bough
#

Kind of both

#

So right now you do .add_system(a) to add something to the default set

#

Or .add_system(a.in_schedule(CoreSchedule::FixedUpdate) for another schedule

#

And base sets are there to keep the pre-0.10 ordering within the default schedule, Main

#

But on main you do .add_systems(Update, a)

#

Or .add_systems(FixedUpdate, a)

quiet cairn
#

ahh interesting, makes sense

strong bough
#

And instead of having those weird base sets, they are now all schedules

quiet cairn
#

so youre saying for me, the issue was this code:

app.add_systems(
              (
                  Self::move_player,
                  ... other systems
              )
                .in_set(CoreGameSet::Main), (i changed it from in_base_set, still didnt work)
      )

and i need to instead do .in_schedule(CoreSchedule::FixedUpdate)?

strong bough
#

You do both the .in_set and .in_schedule

#
            .add_systems(
                (simulate_inputs,)
                    .in_set(Set::Input)
                    .in_schedule(SimSchedule::Resimulation),
            )

An example from my code setting something in a specific set in a custom schedule

quiet cairn
#

ahh, is this because a Set does not necessarily exclusivly belong to one schedule?

strong bough
#

Yes, you can specify a set to behave differently in every schedule if you want

quiet cairn
#

i think my understanding was once i created CoreGameSet and told it to be a part of FixedUpdate, that it was enough to just tell my systems to be in CoreGameSet. Now this makes sense

#

that was the foundation i was missing to understand all this, thank you!

#

huh, i made that change and a lot of my game functionality is now bonked lol. some things seem to run very very slow

#

is .insert_resource(FixedTime::new_from_secs(1./60.)); the correct way to show 60FPS ? or is it 0.6 fps?

strong bough
#

1./60. should be correct yes

quiet cairn
#

it seems like event communication is super delayed. My mouse input system detects a left mouse button instantly, but the response from the animation system is non existant or very very delayed (like 10-15s)

#

but player movement is totaly fine

strong bough
#

This might be an issue with events getting lost

#

The events get swaped during First, but there's no guarantee that your FixedUpdate runs at least once every 2 frames

quiet cairn
#

that seems like the case, because sometimes when i start up my world generation (uses lots of events) doesnt generate entities, sometimes it does

quiet cairn
#

what if i make my frame rate 120 to match my tick rate?

strong bough
#

The way I work around this is by setting my events up to get cleared in FixedUpdate. But that obviously only works on events you control

quiet cairn
#

hmm, i dont think i make use of any events outside of my own (but crates could be using events internally i guess?)

strong bough
#

You can also sort of work around it with a really ugly hack. See the event is added to the default schedule, but the default schedule doesn't have to be Main, I have some plugins I want in FixedUpdate, so I change the default, add the plugin, then set it back ๐Ÿ˜‚

quiet cairn
#

LMAOO thats jokes

#

also funny discovery, if i unplug my mac the animations work instantly, and if i replug, they get all janked

#

this is so wild haha

#

makes sense, but kinda funny

strong bough
#

But in most cases I just set up systems that respond to input to run in Main, and they then process those inputs into some event that actually goes to the systems that execute logic

#

Those events with the actual logic then get cleared only in FixedUpdate

quiet cairn
#

hmmm that would require a looot of refactoring on my end

#

a lot of my input system handles the action of the input as well

#

but wait no, this only applies to sending events

#

sorry, trying to wrap my head around this

strong bough
# strong bough You can also sort of work around it with a really ugly hack. See the event is ad...

Speaking of this hack ... I made this beautiful mess exactly to make abusing that hack easier:

trait AppExt {
    fn with_default_schedule(&mut self, s: impl ScheduleLabel, f: impl Fn(&mut App)) -> &mut App;
}

impl AppExt for App {
    fn with_default_schedule(
        &mut self,
        schedule: impl ScheduleLabel,
        f: impl Fn(&mut App),
    ) -> &mut App {
        let orig_default = self.default_schedule_label.clone();
        self.default_schedule_label = Box::new(schedule);
        f(self);
        self.default_schedule_label = orig_default;
        self
    }
}
#
        .with_default_schedule(SimSchedule::Simulation, |app| {
            app.add_plugin(PhysicsPlugin)
                .add_plugin(SkillsPlugin)
                .add_plugin(MovementPlugin)
                .add_plugin(CombatPlugin)
                .configure_sets((Set::Cleanup.after(PhysicsSet::Writeback),));
        })
quiet cairn
#

System A: Handles input reading, creates an event, lives in Main schedule
System B: Reads event from A, does action, lives in FixedUpdate schedule

strong bough
#

Yes, that's how I have it mostly set up

quiet cairn
#

wait so if i did that, and added my events inside that callback fn it would work? ๐Ÿ‘€

strong bough
#

Yes, every event registered by plugins there would be in the schedule you configured

#

It's really ugly, but then again we might get fixes to events and input timestamps (so input will feel more precise, even if it is processed at a lower framerate) in the near future so it's mostly just temporary

#

Tho obviously things like moving your camera should never be in the FixedUpdate schedule

quiet cairn
strong bough
#

Yes, and it's also a big meme to give higher refresh displays a limited FPS camera movement

#

If you're at 60FPS it can be surprisingly hard to get exactly 1 fixed update per frame, with 120 it becomes a smaller issue, but then you start expecting things to move smoothly

quiet cairn
quiet cairn
strong bough
strong bough
quiet cairn
#

huh so i used your hack trait impl on App to add my attack event to the FixedUpdate schedule, but it seems to cause attacks to animate slower?

#

probably makes sense if timers tick slower when i cap the frame rate?

strong bough
#

If animations run on a fixed delta that would make sense yea

quiet cairn
#

im trying to wrap my head around how the two can be disconnected (player translation systems vs player animations)

It seems like with or without my laptop plugged in, i get the player movign at the same speed. But when laptop is plugged in, animations run slower

#

is it because the internal systems that tick the timers arent part of fixed update? nvm that doesnt make sense... or does it?

strong bough
#

Usually I'd expect animations to run in Main, using delta time to make it always run at the same rate regardless of FPS

quiet cairn
#

just gotta go aroudn and hack in all my events now ๐Ÿ˜› thanks for the help!

quiet cairn
#

Hmm, with regards to the Camera movement, how do i keep the camera moving at the same speed across tick rates if its not part of FixedUpdate? It seems like I have to lock it to the frame rate, and probably allow a setting to chagne frame rate in the game itself to allow for higher refresh rates?

serene shadow
#

You can use Res<Time> and time.delta_seconds()