A common pattern in ECS seems to have entities that store data to manage the lives of other entities. (E.g. spawner & particles, gun & bullets, etc.) Many database systems, which is what ECS really is, support data locality for these kinds of relationships. For example, Spanner has interleaved tables. I wonder if ECS has some set of best practices or even code to enable working with N:1 relationships like these?
Here’s a real example, because the above might be a bit abstract:
I’m using Entities to write a simple particle system, mainly as a learning exercise. Each particle has the Entity number (foreign key, really) of the entity that acts as its spawner.
This seemed like a good way to structure the data:
public struct SpawnerData : IComponentData {
public int MaxParticles;
public int LiveParticles;
}
public struct ParticleData : IComponentData {
public Entity Spawner;
}
Writing the spawner system is easy:
public class SpawnerSystem : SystemBase
{
protected override void OnUpdate()
{
var ecb = _endSimulationEcbSystem.CreateCommandBuffer();
Entities.ForEach((ref SpawnerData spawner, in Translation translation) => {
// .. Obvious spawning logic using an EntityCommandBuffer
}
}
}
Destroying particles, though, is not as nice. In order to keep the LiveCount property up to date, you have to look up the Spawner, like so:
if (HasComponent<SpawnerData>(particleData.Spawner))
{
var spawnerData = GetComponent<SpawnerData>(particleData.Spawner);
spawnerData.LiveParticles--;
ecb.SetComponent(particleData.Spawner, spawnerData);
}
Now the thing with this code is that you have to keep calling GetComponent in the ForEach. Of course, it’s not a big deal - data will still be reasonably local and GetComponent is probably cheap enough. But this type of thing seems to come up often enough that having a builtin way to ensure the lookups are optimalized would probably help bunches.