#How to change camera behavior based on app state?

12 messages ยท Page 1 of 1 (latest)

fair violet
#

I have a camera entity that I want to change its behavior based on the current app state (e.g., in-game, main menu, splash screen). I've tried to use the app state in a Bevy system to modify the camera's properties, but I'm encountering a trait-bound error that I can't quite resolve.

Here's a simplified version of my code:

#[derive(Resource)]
pub struct Camera(Entity);

fn spawn_camera(mut commands: Commands) {
    let camera = commands.spawn(Camera2dBundle::default()).id();
    commands.insert_resource(Camera(camera));
}

fn camera_system(camera: Res<Camera>, app_state: State<AppState>) {
    match app_state.get() {
        AppState::Gaming => {
            println!("{:?}", camera.0);
        }
        _ => {}
    }
}

pub struct CameraSystem;
impl Plugin for CameraSystem {
    fn build(&self, app: &mut App) {
        app.add_systems(Startup, spawn_camera);
        app.add_systems(Update, camera_system);
    }
}

#

In the code above, I'm trying to use the app state (AppState) to change the camera behavior when the game is in the "Gaming" state. However, I'm getting the following error:

#

Could someone help me understand how to properly use the Bevy app state to change the camera behavior based on different game states and resolve this error?

Additional Information:

  • AppState is an enum that represents different game states.
  • I'm using Bevy version 0.11.3
polar thorn
#

It looks like camera_system has an invalid function signature for a system. I haven't tried accessing a state in a system like that before, so I'm not sure if that's not possible or maybe the type on app_state is wrong.

#

If you just need to toggle something on the camera upon switching states, I'd use:
.add_systems(OnEnter(AppState::Gaming), set_gaming_mode)

#

Or if you want to just run different camera logic, you can use:
add_systems(Update, gaming_camera.run_if(in_state(AppState::Gaming)))

#

Double checked, the type is wrong, it should be app_state: Res<State<AppState>>

last hinge
#

Is it more Bevy idiomatic to match on the state in the system, or to dispatch different systems depending on the state?

fair violet
#

@polar thorn Thank you, you helped me to get the point.

By set the AppState as a Resource I must to insert that resource in one point of the app, but this doesn't make sense to me, to get the state and after that change the settings of the camera in a specific state is quite redundant, so, in order to achieve the same goal it must to be better just use a filter in the system and run it in the desired state, and after that set the camera as a attribute in the function signature to change the settings by state, based on the native Bevy implementation of State, with out biggest changes.

I'm going to test and see if I can solve it ๐Ÿ˜๐Ÿ˜

#

@last hinge I think that is more idiomatic dispatch the systems by state, look better and I guess that is easier to read.

But... ๐Ÿ˜…๐Ÿ˜…
That is just my opinion, I really don't know what is better, I'm learning right now and this is my first project, so, don't take me so seriously ๐Ÿคฃ

I got that conclusion by the bevy documentation, if we have the camera as a component, then just the systems should to change it and it is better, at least to me, run just the correct systems by state

polar thorn
#

Adding a state enum to the app creates that Res<State<StateEnum>> for you, as well as a Res<NextState<StateEnum>> that you should use for state transitions to trigger the OnEnter/OnExit behavior.

As for which is preferred, I would think it depends on how different the behavior is. If it's nearly identical with like a few number differences, doing a match on app state is probably better. But if there's a significant difference, like following players vs being mostly static vs using some cinematic spline I'd probably go with different systems with run_if conditions

#

Basically whether each state needs to perform different queries/access different resources etc to perform its logic should probably be your deciding factor