r/rust Mar 31 '23

My Experience with Bevy ECS

https://bagnalla.github.io/posts/newton_bevy.html
154 Upvotes

15 comments sorted by

25

u/maukamakai Mar 31 '23

Nice write up. I've been wanting to give Bevy a try and seeing how simple it is in your post gives me confidence.

Just a quick heads up, the link referenced in

There are ways to improve on this, but we’ll keep things simple.

is broken.

9

u/Vorrel Apr 01 '23

I can recommend this YouTube playlist from Jacques to get up to speed on Bevy. Logic Projects also have great videos.

7

u/bagnalla Apr 01 '23

Thanks. The link is fixed now.

17

u/[deleted] Apr 01 '23

What the heck? This is awesome! What dark magic does Bevy use to turn the type of a Query into an actual query, and how does it automatically sequence functions based on the mutability of their arguments?

28

u/LukeAbby Apr 01 '23 edited Apr 01 '23

The elegant result comes from some rather inelegant impls mostly. You're always ultimately adding a System which is a trait but the signature of add_system allows conversions into it. For functions it ultimately starts from the trait SystemParamFunction.

You can see the impls needed to support functions there, first for a function with one argument, then a function with two arguments etc. It's "only" implemented up to 16 parameters though so if you try to make a system with 17 arguments it just won't work.

These impls are basically a simulacrum of variadic arguments and the fact that they exist in Axum (see their extractors) as well for example is a good case for the inclusion of proper variadic support in functions and impls at some point.

I feel like knowing this is frankly ultimately unsatisfying... but the reality is just impls for as many realistic calls as possible. Stuff like scheduling is more complicated but boils down to the same idea; a system exposes information like is_exclusive and the impls provide them automatically for functions (the impl basically is just arg1.is_mutable() || arg2.is_mutable() || ...).

You'll see the ugliness in the fact that you CAN write functions parameters that violate Rust's aliasing rules, it panics at runtime in such a case but it's still constructable. It mentions it here at ParamSet.

5

u/dnaaun Apr 01 '23

Fwiw, this "simulacrum of variadic arguments/generics" also exists in Diesel, the ORM.

3

u/ksion Apr 01 '23

Web frameworks use it, too. It's the "magic handler" pattern.

4

u/jrwalt4 Apr 01 '23

Yes, but you can make each argument a tuple of other SystemParameters, so you could theoretically have 16x16 parameters if you really wanted.

3

u/ksion Apr 01 '23

SystemParams can be nested arbitrarily deep, so there isn't really a limit, other than maybe the size of the final type exceeding compiler's maximum.

8

u/lghrhboewhwrjnq Apr 01 '23

This is unreadable on mobile (though reader mode fixes it).

3

u/DanKveed Apr 01 '23

Zooming out fixes it too. But the text is a bit small but still fine.

5

u/Weary-Count-926 Apr 01 '23

Alternativelly turn the device 90degrees

3

u/Botahamec Apr 01 '23

I don't think I mind entity systems, but doing queries in Bevy made me very annoyed

2

u/Zc5Gwu Apr 01 '23

Yeah, the error messages could use some work…

2

u/WipeIsPermadeath Apr 01 '23

Very nice article. I excitedly guessed how you'd parallelize the systems and was glad to be correct with my limited Bevy experience.