Open andriyDev opened 2 hours ago
I generally agree with your criticisms of the state of thing here, but I would like to fully remove schedules in a refactor like this, and explicitly pass in a base set in place of the ScheduleLabel
argument to add_systems(Update, my_system)
. There's too much conceptual overlap.
I generally agree with your criticisms of the state of thing here, but I would like to fully remove schedules in a refactor like this, and explicitly pass in a base set in place of the
ScheduleLabel
argument toadd_systems(Update, my_system)
. There's too much conceptual overlap.
I don't think this is feasible. Schedules can't go away really. The most obvious example is FixedUpdate
. This has to be a schedule since it needs to run multiple times per frame. We can't achieve this with system sets directly. I'd also want to be able to keep saying app.add_systems(FixedUpdate, movement)
, so keeping the Schedule-first API seems good.
We could make schedules lighter weight, especially if we switch to systems as entities. Then a schedule just becomes a system set to run and a cached topo sort. But that's a future ask, and I'm not sure if we need to wait on this. Note this issue requires pretty much no migration guide.
There definitely needs to be a world.run_group_of_systems
API due to the branching control flow :)
We could make schedules lighter weight, especially if we switch to systems as entities. Then a schedule just becomes a system set to run and a cached topo sort
This was exactly the sort of thing I had in mind. I don't think we need to wait on systems-as-entities for this, but it sure would be nice to be able to quickly filter by label like that.
Background
Today, we have many schedules.
Main
,First
,PreUpdate
,Update
, etc. Primarily, these are used for general ordering of systems. This has necessitated a bunch of sad parts likeMainScheduleOrder
. This is just code duplication. We already have a way to order a bunch of systems: system sets! In theory, instead of Update being a schedule, it could be a system set and get basically the same behaviour. In theory we could even have systems that run between PreUpdate and Update (without needing a schedule in between). Schedules reduce parallelism and system set constraints aren't (currently) shared across schedules.Base Sets
In #8079, we removed base sets. I believe this was the correct move at the time. The main problems listed in that PR:
in_base_set
which was different fromin_set
.add_system(foo.after(TransformPropagate))
would fail because foo is implicitly inCoreSet::Update
"Update
is nowhere to be seen, and no way to really "reach" it with "Go to Definition".I am not trying to bring back base sets as they were. However, they have a nice advantage: there's pretty much one schedule to deal with:
Main
.Bringing them back in style
The current syntax for adding systems is very nice:
Let's keep that! I propose adding a trait like:
Then
add_systems
becomes:So far, nothing has changed: we can still add systems to a schedule like normal. We can also still add systems to system sets like normal:
The kicker comes from the next step. First, we need to bring back the
CoreSet
enum (part of it at least):And finally, we change
Update
and friends, to the following:Now look what this does:
Wait... nothing changed... Exactly! Under the hood,
Update
is no longer a schedule. It is a system set in theMain
schedule. Provided that Bevy adds a.chain()
for all theCoreSet
, #9822 will automatically insert a sync point between the "base sets". Now we've just made some syntactic sugar for:User's don't need to learn anything about base sets, they just silently use them. There's also nothing special about base sets. Users can create their own "base sets" by just making a new struct that impls
SystemLocation
.Even rendering can take advantage of this. As far as I can tell, rendering uses one schedule with a bunch of system sets for performance reasons. Now we can have a nicer API:
MainScheduleOrder
can be replaced with justconfigure_sets
calls:Alternatives
CoreSet
implementSystemLocation
. Then ouradd_systems
calls would look likeapp.add_systems(CoreSet::Update, move_donkey)
.add_systems
. (I'm not a fan of this since it reduces what we can do with system sets).Risks
add_systems
. This can be confusing to learn about the difference betweenUpdate
,CoreSet::Update
, andMain
. (it may be confusing that you can add systems to a system set in two ways). I think this is fine since this is mostly just an implementation detail. From a user's perspective they are doing the same thing that schedules do today.Update
and (assuming itsSystemLocation
impl is close), see that it belongs to theMain
schedule.