[FEATURE] Archetypes with pre-defined properties
See original GitHub issueI’d like to propose a new feature: archetypes with pre-defined properties for the components.
The use case would be to have multiple “archetypes” with the same components, but different values for the properties. This would help with a data-driven approach where you chain entity creation (eg. create entity A from data, and when it is deleted, another entity B is created). At the moment, this can be done by using archetypes, but changing properties on the components gets more tricky.
The real-life example is my current project, where I have a custom reflection-based data-driven setup for creating entities. My map loader loads objects which refer to the name of the object definition. The object definition is a JSON which has the component classes with all the properties, like so:
{
"class": "me.manabreak.managame.common.Health",
"properties": {
"health": 10,
"healthMax": 10
}
}
Now, this works fine when loading the levels, taking about a millisecond per entity to construct. However, the issue arises when I’d like to construct a new entity when another one dies. The current approach would be to have a custom component (eg. AfterDeath
) which refers to the definition of the object to create. However, it’s a bit too slow to do the same logic as I do loading the levels; a millisecond per entity is quite a bit if there’s dozens of entities to create per frame.
In the proposed feature, there would be an archetype along with the properties. This way, when defining the archetype, we could store the properties using whatever data source we have, and when the entity is created using that archetype, the properties are filled there.
At the moment, archetypes provide a facade of sorts for the entity mutators. Under the hood, creating an entity from an archetype basically translates to creating a new entity and transmuting it with a previously defined mutator. However, this doesn’t operate at all on the properties.
I’m not quite sure how this feature would be tackled in a performant manner. Deserialization during loading is allowed to have a tiny performance hit, but when a fast-pacing game is running where new entities should be created based on the game events, it gets more critical.
A train-of-thought proposal would be to have a bit of a similar functionality that we have for the pooled weaver, but instead of resetting the properties, we would copy them from the archetypal component.
Would there be any interest for such feature?
Issue Analytics
- State:
- Created 5 years ago
- Comments:9 (7 by maintainers)
Top GitHub Comments
Any particular reason why you aren’t using artemis’ serialization? It works with entity references, one transmuter per unique compositionId, and guarantees that all entity id:s are assigned in the same order as they appear in the json (normally, entity id:s are recycled in FIFO order).
The Prefab use-case is repeated construction of entities-with-component-data - where only some component data requires changing (e.g. Position) . It’s backed by artemis’ serialization. The raw json is cached/reused as a
JsonValue
.Snipping from the tests, but with some comments:
Json from
PrefabData
: some_prefab.json.Entity tag is read from SerializationTag, if available.
I ❤️ imgui! Such a pleasure to work with.
There’s a lot of poor naming and lacking documentation - most of the serialization implementation unfortunately suffers from it.
I’m not quite sure what you mean by world state (if I don’t make any sense, you know why); SaveFileFormat is primarily a description of an entity set with component data. The loading mechanism creates entities and their components using the world instance, so there are no temporary worlds or merges. Loading is additive; Prefabs rely on this behavior for multiple instantiations.
Prefabs are a specialization on top of the serialization api. While prefabs are intended as blueprints for entity “types” (BasicEnemyShip.class, RedDragonBoss.class),
WorldSerializationManager
is more generic, and used for saving/loading arbitrary sets of entities + potentially other state (see SaveFileFormat.java) - use-cases in the vein of full-or-partial level data or player save.It’s described here: https://github.com/junkdog/artemis-odb/wiki/libgdx-json#using-the-serializer
You still have to write some glue yourself though, like where to save to/load from.
With regards to the above snippet, you can obtain an
EntitySubscription
fromworld.getAspectSubscriptionManager().get(aspect)
. Alternatively, if you know the entities by id, pass them directly toSaveFileFormat(IntBag)
.Imo, the only convenient way to work with Prefabs is to have some sort of (in-)game editor; then it’s pretty easy to serialize whatever entities you want saved, and instantiate prefabs as needed (I personally like binding ctrl-c, ctrl-v to save-to-clipboard/load-from-clipboard - and manually pasting prefabs i’m working on into their respective json files).
Help is always welcome 😃
Hope I made some things a bit clearer?