bevy_proto
Create entities in the Bevy game engine with a simple config file.
---
name: "Simple Enemy"
components:
- type: Enemy
- type: Attack
value:
damage: 10
- type: Armed
value:
weapons:
primary: "laser sword"
Installation
[]
= "0.1.0"
Then add it to your app like so:
use ProtoPlugin;
Disclaimer
Before you install it into your project, please understand the limitations of this crate. While it makes working with some entities easier, it may come at a bit of a performance cost depending on your project.
According to the bench example, spawning a Prototype can be about 1.8x slower than defining the
entity in the system manually (this may vary depending on the data being loaded). This difference becomes much smaller
for release builds, but is still a tad slower. For some projects,— except maybe for those that are really intensive or
spawn lots of entities very frequently,— this may not be a problem.
Still, it's good to consider the drawbacks of using this system and see if it's right for your own project. Here's a breakdown of the top current/potential issues:
-
Dynamic Dispatch - This crate uses dynamic trait objects to add or remove any component on a Prototype. However, this comes at a cost since the compiler can no longer know the types in advance, preventing things like static dispatch, monomorphization, etc.
-
Load Time - This is likely not noticeable for smaller projects (although I haven't tested with hundreds of Prototypes myself), but the crate currently does need to load all Prototypes at startup. This is so it can prepare any other needed resources and assets in order to spawn the Prototype.
-
Assets - This crate also (currently) stores all required assets in its own resource
ProtoData. This means that resources that may only be needed once will be kept loaded during the entire lifetime of the application, since it holds onto the handle. This can be prevented by hosting the asset on a separate component and manually creating the handles when spawning that Prototype:// Attach fictional OtherComponent with asset "my_asset" which should unload when despawned prototype.spawn.insert;
With all of that said, this package is meant to speed up development and make changes to entity archetypes easier for humans (especially non-programmers) to interact with. If the performance hit is too much for your project, you are better off sticking with the standard methods of defining entities.
Usage
Creating Components
First, create a struct that implements ProtoComponent. This can be done one of two ways:
For simple components, ProtoComponent may be derived:
use proto_comp;
By default, the fields of a
ProtoComponentare cloned into spawned entities. This can be somewhat controlled via theproto_compattribute, which can tell the compiler to use theCopytrait instead.
Otherwise, you can define them manually (the two attributes are required with this method):
use ;
use EntityCommands;
use *;
use ;
// Required
// Required
A
ProtoComponentdoes not need to be a component itself. It can be used purely as a DTO to generate other components or bundles. You have full access to theEntityCommandsso you can insert bundles or even multiple components at once.
Defining the Prototype
Define the Prototype in a config file. By default YAML (and by extension, valid JSON) files are supported:
# assets/prototypes/my_prototype.yaml
---
name: "Dog"
components:
- type: Creature
value:
species: "Canis lupus familiaris"
legs: 4
By default, all
.yamland.jsonfiles in theassets/prototypes/directory are processed as Prototypes.
Spawning the Prototype
To spawn a prototype, add a system that has access to:
-
mut Commands -
Res<ProtoData> -
Res<AssetServer>
Then write something like the following:
The spawn(...) method returns the EntityCommands used to create the entity. This allows you to add additional
components, bundles, etc.:
let dog: Entity = proto
.spawn
.insert
.id;
Using Assets
For Prototypes that need access to assets, you can get access one of two ways:
The first is by loading the asset when being spawned in. This is preferred because it means the asset can be unloaded when no longer needed.
use EntityCommands;
use *;
use ;
use ;
The second, is by preparing the asset for later use. This retains the asset in the ProtoData resource, which then must
be disposed of manually when no longer needed. Setting up an asset is done via the prepare method:
use EntityCommands;
use *;
use ;
use ;
Custom Prototypes
The default Prototype object looks like this:
However, you can use your own Prototype object. Any struct that implements Prototypical can be used in place of the
default Prototype. Then you just have to supply your own deserializer to the ProtoPlugin object.
use ;
;
All fields in
ProtoDataOptionsmust be specified if you wish to use a custom deserializer. Even if you want to continue using the defaults, you must still specify them. The additional fields shown above are also the defaults if you wish to copy them.