How to write methods that are available to the Entities.ForEach codegen?

I’ve tried feeding directly method calls, but that captures the “this” variable, which isn’t allowed in jobified cases. At the same time I kinda don’t like writing long methods. Is there a way to split whats inside Entities.ForEach delegate into multiple methods?

I’m referring this just in case:

Entities.ForEach((ref Component c) => Method(ref c)).Schedule...;

And .Run as well;

Pretty sure saw a hack somewhere but can’t find it.

At the same time, I could add methods to the structs, but that’ll mess up the whole “Data separately - logic separately paradigm”.

Assuming you aren’t using any instance data you could make the method static. Otherwise, I think you can just create a struct that contains the data and call methods on that struct.

1 Like

When using static methods on the System some functionality like GetComponentData is no longer accessible. Alternatively local functions inside OnUpdate seem to work.

1 Like

Using a struct is the best way to break up the contents of the foreach delegate imo.

Processor processor = new Processor();

this.Entities.ForEach(delegate(Entity entity, ref SomeComponent component) {
    processor.Execute(entity, ref component);
}).Schedule();

...

private struct Processor {
   // Needed variables can be expressed as member variables
   // Populate them during construction

    public void Execute(Entity entity, ref SomeComponent component) {
        ... // Code here that calls other private methods
    }

    private void UtilityMethod() {
        ...
    }
}

You do lose some methods like GetComponent() and SetComponent() like Ryunis said but this can be mitigated by passing ComponentDataFromEntity to your processor struct.

private struct Processor {
    public ComponentDataFromEntity<OtherComponent> otherComponentMap;

    public void Execute(Entity entity, ref SomeComponent component) {
        // This is GetComponent()
        var otherComponent = this.otherComponentMap[entity];

        // This is SetComponent()
        this.otherComponentMap[entity] = modifiedOtherComponent;
    }

    private void UtilityMethod() {
        ...
    }
}
1 Like

That is decent… but using ComponentDataFromEntity is far from ideal. For example, what if the function doesn’t need to fetch certain component data based on an if-statement… or even worse, what if the function needs to fetch different entities based on an entity id stored in a component. The person calling the function has to either fill all possible component data that the function might need, or they’ll have to end up implementing a bunch of the if-then logic within the function and defeat the whole purpose of a function in the first place.

For SetComponent(), AddComponent(), and RemoveComponent() you can pass in an EntityCommandBuffer or a EntityCommandBuffer.ParallelWriter which follows encapsulation principals quite nicely. For GetComponent()… ugh… I got nuthin. I’ll let you all know if I figure something out. I might end up using local functions within the foreach like @Ryunis suggested… but man it’s so ugly.