Architecture feedback wanted - I more and more find myself applying a pattern that encodes structural state in the actual ComponentData itself, e.g.
struct Aim : IComponentData
{
public bool enabled; //this, rather than the presence/absence of the Aim component on an entity!
public float3 position; //Data is interpreted / ignored depending on state
public Entity target; //I also tried to interpret the data as state directly, but it reads ambiguously and masks broken contracts ("target cannot be Entity.Null")
}
And then I have systems ignore the entities where enabled is false. (i.e. if (!aim.enabled) return;
)
In this case, because whole kinematic hierarchies of objects aim based on what the main actor sees, I can also just copy this component down to the dependents instead of changing the structure on 3 entities x number_of_guns_on_a_ship every time I run out of targets.
While I believe this saves the burden and memcpy that structural changes can bring with them, and keeps entity state available earlier (not at the sync point of whatever structural change ECBS you’re recruiting to do the work), it does cause the system to run for a lot more entities.
In other cases, it saves me a second system that works on entities that don’t have the component, but need to add it, etc. But it means my primary system now does twice the work. I find that if the work is simple enough (e.g. < 2x the amount of code the considerable boilerplate and dependency headache of a System would be), it is well worth the trade-off.
A last advantage, it also makes the system much more parallelization friendly (also by merit of having fewer systems accessing the same data).
What are your thoughts? Is “state in structure” better or worse than “state in data”? What are the cases where you opt for one or the other?
How do you make structural changes require less boilerplate (get the right ECBS, get EntityCommandBuffer from ECBS, don’t forget to make it concurrent, add producer handle to ECBS…)