#Res Time suddenly doesn't update

63 messages ยท Page 1 of 1 (latest)

hollow canyon
#

Neither the delta nor elapsed value of the bevy Time resource seems to update soon after my app runs. It will show the exact same respective values across systems and states every frame. The systems still run many times per second, to the point where it makes it impossible to even close the window.

All my app does at the moment is it reads a 240x188 pixel image file, waits until it's loaded, then for every pixel it spawns a PbrBundle with a repeatedly cloned cube mesh and a new material from the color value of the pixel.

IIRC the Time problem showed up after introducing States into the app. Refactoring to not use states makes the Time problem go away. Also, removing the part where a new material is created for each pixel doesn't have the problem.

The only plugins I'm using are the DefaultPlugins with LogPlugin configured.

I looked at the bevy_time time_system code and see it says that the render world updates the time in this case, and there seem to be hints in that direction, but I don't know how to interrogate it further.

fervent umbra
#

Are you perpetually looping your stages?

#

Using states

#

And presumably you're not messing with the time rate...

hollow canyon
#

State transitions are still working

#

like I'm just using State.set(new_state) and it will run the system set configured for that state, and then it works back again

fervent umbra
#

Hmm. And you're sure you're advancing frames?

#

iyes_loopless states would avoid endless looping, if that is your problem

#

Time is only updated once per frame

hollow canyon
#

It's not rendering new frames (and time is not updating) when I spawn the new materials. When I just use the default material it will render.

fervent umbra
#

Okay so my guess is definitely that you have a bug in your state transition logic

hollow canyon
#

A bug in state transition logic just from adding new materials to Assets<StandardMaterial>>?

#

I don't think I have any control flow linked to it, as I'm just sticking it in the PbrBundle right away.

fervent umbra
#

Can you link your code, or ideally make a minimal reproduction?

hollow canyon
#

Yeah. Can I upload it here as an archive or do I have to use a git host?

fervent umbra
#

Either is fine ๐Ÿ™‚

#

I'll take a look tomorrow ๐Ÿ™‚

heavy owl
#

Time is updated once per frame

#

I would check to see if you're not letting the frame end

#

I'm led to assume your states are repeating forever and never letting the first frame end

hollow canyon
#

I'm just wondering why the loading of materials is causing that loop to occur.

heavy owl
#

hmm, the only loop I think could happen is the code goes back and forth between tick and end_tick

#

but it doesn't look like the timer finished check in end_tick would always pass

#

idk

#

states have some weird behavior rn

#

IIRC if you enter a state, that'll run its on_enter system set and its on_update system set in quick succession

#

we've been preparing an improved scheduling API, so it's been a while since anybody's looked at this stuff

hollow canyon
#

the time check in end_tick is just there for debug output. The system unconditionally just sets the state back to the one that runs tick

#

i cant into code tags

heavy owl
#

if this always passes, then you'll be stuck in a loop

    if tick_timer.as_ref().unwrap().finished() {
        // debug!("tick");
        app_state.set(AppState::Tick).unwrap();
        tick_timer.as_mut().unwrap().reset();
    }
hollow canyon
#

and then tick just runs repeatedly until a certain time ahs passed and the sets the state that runs end_tick

#

the AppState:Tick runs only the end_tick system

#

and then end_tick sets Appstate::Running which only runs the tick system

#

sry if its confusing

heavy owl
#
  • tick runs and sets the AppState to Tick
  • setting the AppState to Tick will run the on_enter and on_update systems for Tick
  • end_tick runs and sets the AppState to Running
  • setting the AppState to Running will run the on_enter and on_update systems for Running
  • (still on the same frame) tick runs again
  • if tick sets the AppState to Tick again, you'll repeat this whole loop
#

does anything change if you increase the timer duration from 0.6 to like 5 seconds?

#

OH

#

actually nvm

#

something else to know is that time.delta() will be Duration::ZERO until the beginning of the 3rd frame

#

there's a good reason for that, but it's still an arbitrary thing that isn't really documented

hollow canyon
#

AFAIK im not even accessing the time resource until setup_world runs on frame 3+, and that just for debug output

heavy owl
#

the frame won't end as long as there's a state transition queued

hollow canyon
#

and even without changing all the calls to time.delta(), the app still runs as intended UNLESS in the setup_world system I add a bunch of materials

heavy owl
#

what I think is happening

#

is that setup_world takes just long enough that time.delta() is greater than 0.6

#

and you get stuck in the endless loop that I described above

#

where you keep going back and forth between AppState::Tick and AppState::Running and the frame never ends

#

so every time tick runs, time.delta() is still the same value > 0.6 and that if statement is always true

#

like the way you have this setup

#

if time.delta() is ever greater than 0.6, you'll get stuck

hollow canyon
#

oh i think i see what youre saying

heavy owl
#

I think you should move this out of end_tick into some new system

app_state.set(AppState::Running).unwrap();
#

like you need to let the current frame end first, and then you can set the state back to Running

heavy owl
hollow canyon
#

I think my problem was assuming that States were just like a filter for which systems are supposed to run each frame. I didn't know it could loop inside a single frame like that.

heavy owl
#

honestly not your fault

hollow canyon
#

I could have read the cheat-book more carefully ๐Ÿ˜‰

heavy owl
#

people run into this kind of stuff a lot, we've wanted to replace this for a while

#

like more than a year

#

should be in the next release tho

#

0.10

#

I think what you want to do would look something like this in the new API

fn main() {
    App::new()
        .add_systems(
        (
            tick.run_if(state_equals(AppState::Running)),
            end_tick.run_if(state_equals(AppState::Tick)),
        )
            .in_set(CoreSystems::Update)
            .chain()
        )
        .add_system(
            apply_state_transition::<AppState>()
                .in_set(CoreSystems::ApplyStateTransitions)
        );
}
hollow canyon
#

For now I'm getting by with just setting a resource and returning if it's not there.