Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECS: Consider removing default deferred operations. #41

Open
christopher-buss opened this issue Mar 10, 2023 · 1 comment
Open

ECS: Consider removing default deferred operations. #41

christopher-buss opened this issue Mar 10, 2023 · 1 comment
Labels
enhancement New feature or request

Comments

@christopher-buss
Copy link
Member

Original Motivation:

Deferring Changes

Q: Why do we defer changes to entities?

A: Internally, queries store a reference to any archetype that matches the current query. When we enter a system, we iterate over each archetype and then iterate over each entity in that archetype. The problem with this is that we if were to add or remove components from entities, the entity could no longer match the given query. We would end up mutating an array that we are iterating over, which is a recipe for disaster!

There are different ways around this, but instead, we opted for the "most simple" approach. Rather than updating the archetype immediately, we simply queue up the changes to be applied at a later time.

Whenever world.flush() is called, we apply all of these changes at once. If you are using the in-built scheduler, this will be called automatically at the end of each system for you, so you do not typically need to worry about it. The only time you should need to call it manually is if you decide to manage anything that interacts with the world outside of the scheduler.

Q: Is creating a new entity deferred?

A: No. This is because components are not added to entities immediately. An entity can exist immediately because it will not be able to match any queries until it has at least one component. This is not true for entity removal, this operation is deferred.

Q: Is state changed in the world deferred?

A: No. If a system processes one entity and changes the component data, this change will be reflected in the world immediately. This is because the world is not a snapshot of the current state of the world, but rather a reference to the current state of the world. This is for performance reasons.

Although the ability to defer operations adds less complexity for the user, many queries will never make modifications to their own underlying archetypes. It would likely be beneficial to allow the user to defer operations to the end of a query, only when they are actually needed to be!

The proposed idea would be to add a defer function, where only the operations within the defer would be called (a bit like task.defer() but contained within the ecs system. world.flush() woud still be used to clear these changes.

world.defer(() => {
    world.addComponent(id, Position);
});

This means that by default, all operations will not be deferred, reducing the overhead, while also ensuring that the overhead is only seen when the user explicitly wishes to defer an operation.

@christopher-buss christopher-buss added the enhancement New feature or request label Mar 10, 2023
@RigidStudios RigidStudios moved this to 📋 Backlog in ECSv1 Mar 15, 2023
@TrippTrapp84
Copy link
Contributor

Agreed completely, it's not very responsive if I have to wait for all of my changes to be applied, and feels like it's very easily going to just cause hard to fix bugs if someone forgets that. An emulation of the task.defered pattern seems best.

HOWEVER, I think we need debug-environment-only checks to warn users if/when they modify components that are currently being targeted by the query. I'm not going to raise an issue on that, it's a down the line thing, but I think it should be considered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: 📋 Backlog
Development

No branches or pull requests

2 participants