schell / apecs

An asyncronous and pleasant entity-component system for Rust
46 stars 3 forks source link

with_system_barrier fails to build schedule #4

Closed luisdanieldlcg closed 10 months ago

luisdanieldlcg commented 10 months ago

First of all thanks for creating this lightweight ecs, i feel like others are just bloated..

I'd like to know what would make ecs::World::tick() return the error: can't build schedule.

This is happening after setting a barrier to make my render system run after all the others (check line 26):

image

Just in case, this is how I'm ticking the world:

image

and the error im getting:

image

luisdanieldlcg commented 10 months ago

I just realized it gives more contextual information when using {:?} however it is kind of confusing to me: image

When it says it cannot run in the same batch as "camera_update" what does it means?

schell commented 10 months ago

@DanikingRD thank you for the kind words! It's tempting to make apecs hold more and more responsibility as I use it for more and more of my programs, but I try to keep it as minimal as possible without compromising its features so your words are encouraging :).

Now as for the error - it seems camera_update and setup can't run together because they both mutate the same resources. For some reason the scheduler is having a hard time solving the constraints.

Now a couple of questions:

It could be that there is a cyclic dependency or a situation that cannot be solved. Or it could be that the solving algorithm is not sophisticated enough to solve this. Or it could be a bug in my implementation. Or it could be that the dependencies are not being specified "correctly", whatever that means.

I think one improvement I could make right off the bat is printing all the constraints on error.

luisdanieldlcg commented 10 months ago

Right so i was able to fix it by making the setup system run before the camera_update. My understanding of this is that since the camera_system will query all the cameras in the world and update them accordingly, while setup creates the player camera, they can't run together. Setup is only called once though.

I have a few questions regarding how the ECS work that i'll drop down here because i don't want to clutter your issue list >_<:

  1. It seems like World::get_sync_schedule_names() returns the exact order at which systems will be executed?
  2. If World::get_sync_schedule_names() does what i asked above then each array are the systems that run together i.e systems that run in parallel? (e.g ["setup", "terrain_setup"] it means they would both run at the same time?)
  3. Given that other ECS do not require you to specify the name of the system i wonder if it would be possible make the systems register with the same name of the function, i.e with_system(setup) would be same as with_system("setup", setup). This is because when you start having lots of systems it becomes difficult to keep track of naming, sometimes i rename systems and i have to rename everywhere.
  4. Is this a good use case for CanFetch?:

image

It seems to be just a way to group Read, Write, Querys of a system right? Also for some reason importing CanFetch doesn't seems to be importing it so you have to use apecs::*. Is that intended?

I know those are lots of questions but I'm currently using this ecs for my voxel engine and i want to make sure i understand how everything works because this is quite a big project.

I'm also willing to help you on any technical difficulties you face regarding question 3 in case you think it could be a good default feature.

Thanks beforehand and feel free to close this issue when you are done

schell commented 10 months ago
  1. It seems like World::get_sync_schedule_names() returns the exact order at which systems will be executed?

It returns Vec<Vec<&str>> where the outer vector are the "batches" and the inner vector are the systems in each batch. Systems in a batch run in parallel/concurrently until all systems in the batch are complete. Each batch run in serial because of data access (resource) constraints.

  1. If World::get_sync_schedule_names() does what i asked above then each array are the systems that run together i.e systems that run in parallel? (e.g ["setup", "terrain_setup"] it means they would both run at the same time?). Yes, for example if World::get_sync_schedule_names returns:

    [
    ["setup", "terrain_setup"],
    ["render"]
    ]

    Then setup and terrain_setup will run first, together, and then render will run after they are both finished.

  2. Given that other ECS do not require you to specify the name of the system i wonder if it would be possible make the systems register with the same name of the function, i.e with_system(setup) would be same as with_system("setup", setup). This is because when you start having lots of systems it becomes difficult to keep track of naming, sometimes i rename systems and i have to rename everywhere.

  3. Is this a good use case for CanFetch? ...

Yes I think that's a great usecase. I'll have to look a bit more into it to see how to make that work, but it seems like a nice thing to put on the roadmap. I welcome any and all help! Glad you're getting some use out of the library :)

Oh, also - in your CameraSystem<'a> if I remember correctly I think you can get rid of the lifetime and use &'static because the query doesn't actually care about the lifetime (it doesn't get used for anything) - it only cares about whether the borrow is mutable.