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

Component Lifecycle Terms #18

Open
xentripetal opened this issue Apr 29, 2024 · 9 comments
Open

Component Lifecycle Terms #18

xentripetal opened this issue Apr 29, 2024 · 9 comments

Comments

@xentripetal
Copy link

xentripetal commented Apr 29, 2024

Hey I really like the direction you're taking this library! I've been bouncing between different ECS libs and this seems like a great option.

It would be very helpful if queries had support for defining filters based on the lifecycle of components.

Mainly:

  1. Changed<T> - Evaluates to true when component T was accessed mutably or set for the entity since the last execution of the query

  2. Added<T> - Evaluates to true when component T was added to an entity since the last execution of the query

I'm not fully sure how bevy does this but it seems like they store a vec of watermarks alongside each column that gets updated each time an entry in the column is accessed mutably or added. Then each query tracks a watermark of when it was last ran it uses for comparison.
https://github.com/bevyengine/bevy/blob/main/crates/bevy_ecs/src/change_detection.rs
https://bevy-cheatbook.github.io/programming/change-detection.html

  1. Removed<T> - Evaluates to true when component T was removed from an entity since the last execution of the query

In bevy, removals publish out an event that systems can read if they run the next frame https://github.com/bevyengine/bevy/blob/main/crates/bevy_ecs/src/removal_detection.rs

@xentripetal
Copy link
Author

Also wanted to give you a heads up that I posted a MR benchmarking this lib Doraku/Ecs.CSharp.Benchmark#29

Showed really great results

@andreakarasho
Copy link
Owner

On my list!
but not sure what would be the right strategy to apply honestly, because components access is always by ref. So everytime you access ref entity.Get<T>() (or when quering) it will set the component as Changed<T> [?]

@xentripetal
Copy link
Author

Hmm, yeah adding variations for ref vs non ref would make the query gen way too large.

I wonder if you could introduce wrapper component types like

public ref struct ChangeTracked<T> where T : struct
{
    public ChangeTracked(Ref<T> value)
    {
        _value = value;
    }

    private Ref<T> _value;
    public bool Changed = false;

    public T Value
    {
        get => _value.Value;
        set
        {
            _value.Value = value;
            Changed = true;
        }
    }
}

that would be automatically handled by the query system to resolve down to T ComponentInfo and update the cell watermark when changed

@andreakarasho
Copy link
Owner

I'm not sure about that.
I put on the table this too: https://github.com/SanderMertens/flecs/blob/master/docs/Queries.md#change-detection

@xentripetal
Copy link
Author

I've started working on a POC where that's stored alongside the component array for chunks
xentripetal@8dca1e2#diff-58f635af42e8d7ed9ebdcb7026ea8163e9fda76b51eefc446bb8ca91fe50a015R11

Add tracking is easy, but I'm not sure how to do the Change notifications either. I think your only options are

  1. Introduce a wrapper type for components
  2. Have a manual NotifyChanged method you can do on the EntityView
  3. Support non-ref struct queries

@xentripetal
Copy link
Author

xentripetal commented May 2, 2024

Though you likely want some way for a query to denote what components it reads vs writes, that way you can start tracking the dependencies of systems for parallelization. So IMO if theres a path to 3, thats the best option.

I believe flecs does it with a NotifyChange and supports parallelization via manually annotating queries

@andreakarasho
Copy link
Owner

More a proof of concept than anything, not sure if it will work with the full functionalities set like bevy:
main...feat/change-detection

@xentripetal
Copy link
Author

xentripetal commented May 5, 2024

Nice! How does that Removed flag work? If it gets flagged on the old archetype then the old arch row is marked as invalid and won't track anything

@andreakarasho
Copy link
Owner

Pushed more commits.
Looks like it starting work. Unfortunately I have no clue how to implement the Each<> methods.

Good catch about the removed component. I didn't realize until now that you just posted the solution with your first post! Basically bevy uses the events under the hood

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants