Hacker News new | ask | show | jobs
by noelwelsh 826 days ago
ECS is basically a very simple relational database. There is no equivalent of foreign keys or other constraints between components. I can't say, for example, "every entity that has a location must also have an associated mesh". If I forget to add a component it's just a silent failure. Everything runs fine, just the expected result doesn't happen.
3 comments

I wonder if a compile-time array-of-structs (AoS) to struct-of-arrays (SoA) transformation like the one done by Zig [1] could fix that issue.

[1] https://zig.news/kristoff/struct-of-arrays-soa-in-zig-easy-i...

You can probably write runtime tests for this. Some system which queries for component Location, and then does an assert for each component that the associated entity also has a mesh.

Granted, this is annoying and not a particularly great solution, but it would serve to give you a reminder for when you forget. I don't mean to diminish from your overall point either, it's a valid and good one I think.

Yeah, runtime checks are not very desirable.

I have this vague thought that Rust needs a different kind of type system.

Standard type systems[0] basically rely on references between values[1]. I seem to read about numerous Rust systems that don't use references for various reasons. Usually the borrow checker gets in the way or they want a different memory layout[2]. This makes me think that what's needed is a type system that allows constraints to be expressed between values without requiring a reference between them. I don't know what this type system looks like, though.

[0]: Rust's type system is a fairly standard type system from an academic POV. The novelty is that it's the first language with traction to use a linear / affine type system, but these are relatively well studied in academia.

[1]: The theory is not formulated this way, but the representation they compile into is a bunch of references.

[2]: ECS, as I understand it, is not a reaction to Rust's type system but an architecture driven by memory layout, parallelism, and breaking-out-of-OO-hierarchy concerns. However the net result is the same.

Totally agreed, like when using an int to reference into an array, there's no way to guarantee that the int won't be out of range, so it needs a check every time

Also no ideas here, but its fun to think about anyways

In theory this is what Bundles are for, though it's easy to not realize that there's a bundle for what you want to do.

I should note that this is a problem with most game engines, not something unique to Bevy. For example, Unity is infamous for requiring arcane combinations of components to avoid silent failures.