Relevant official examples:
Bevy stores and manages all your data for you, using the Bevy ECS (Entity-Component System).
Conceptually, you can think of it by analogy with tables, like in a database or spreadsheet. Your different data types (Components) are like the "columns" of a table, and there can be arbitrarily many "rows" (Entities) containing values / instances of each component.
For example, you could create a
Health component for your game. You could
then have many entities representing different things in your game, such
as the player, NPCs, or monsters, all of which can have a
(as well as other relevant components).
This makes it easy to write game logic (Systems) that can
operate on any entity with the necessary components (such as a health/damage
system for anything that has
Health), regardless of whether that's the
player, an NPC, or a monster (or anything else). This makes your game logic
very flexible and reusable.
The set / combination of components that a given entity has, is called the entity's Archetype.
Note that entities aren't limited to just "objects in the game world". The ECS is a general-purpose data structure. You can create entities and components to store any data.
Bevy has a smart scheduling algorithm that runs your systems in parallel as much as possible. It does that automatically, when your functions don't require conflicting access to the same data. Your game will scale to run on multiple CPU cores "for free"; that is, without requiring extra development effort from you.
To improve the chances for parallelism, you can make your data and code more
granular. Split your data into smaller types /
structs. Split your logic
into multiple smaller systems / functions. Have each system access only the
data that is relevant to it. The fewer access conflicts, the faster your
game will run.
The general rule of thumb for Bevy performance is: more granular is better.
You may be used to thinking in terms of "object classes". For example, you
might be tempted to define a big monolithic
struct Player containing all
the fields / properties of the player.
In Bevy, this is considered bad practice, because doing it that way can make it more difficult to work with your data, and limit performance.
Instead, you should make things granular, when different pieces of data may be accessed independently.
For example, represent the Player in your game as an entity, composed of
separate component types (separate
structs) for things like the health,
XP, or whatever is relevant to your game. You can also attach standard Bevy
Transform to it.
This will make it easier for you to develop your systems (game logic / behaviors), as well as make your game's runtime performance better.
However, something like a
Transform, or a set of coordinates, still makes
sense as a single
struct, because its fields are not likely to be useful