bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.4k stars 3.59k forks source link

Docs for ".entry()" in EntityCommands is confusing / incomplete #16379

Open viridia opened 1 week ago

viridia commented 1 week ago

How can Bevy's documentation be improved?

This relates to the new .entry() API for manipulating components. Specifically, the documentation doesn't make clear how to do a "get or insert" type of operation, which is what I think most users want. Specifically, the code example for .entry() looks like this:

    /// fn level_up_system(mut commands: Commands, player: Res<PlayerEntity>) {
    ///     commands
    ///         .entity(player.entity)
    ///         .entry::<Level>()
    ///         // Modify the component if it exists
    ///         .and_modify(|mut lvl| lvl.0 += 1)
    ///         // Otherwise insert a default value
    ///         .or_insert(Level(0));
    /// }

This example seems to imply that if you want to modify a component in place, or create a new component if it does not already exist, then you have to specify the component values twice: once for the "already exists" case, and once for the "create new" case. In this example the component only has one field, but for something like Node this would be onerous. My mistaken understanding caused me to avoid using this API for a long time - thinking it wasn't that useful - until someone on Discord informed me about the .or_default() option.

My suggestion is that the docs for .entry() should include an example which is less artificial, and more like a typical use case: "get the component if it exists, create it if it doesn't, and then let me specify the parameters one time."

alice-i-cecile commented 1 week ago

Note that the order in which you call .and_modify vs .or_default / or_insert matters! If you want to insert and then modify something, initialize it first. If you want to only modify the value if it exists, do the reverse.