The Ingredients
DCES
provides a dense ECS rust centric
architecture. The interaction with DCES
is managed via the Entity Component Manager
(ECM), a wrapper API.
In contrast to the Object Oriented Programming
(OOP) paradigma, the
DCES separates data from behavior. Behaviors are handled via
systems. Systems provide the logic and implement the behavior on how
to act on entities with given properties. Data are bound to
components that are assigned to entities. Thus entities are unique
identifiers, that may have multiple, dynamically changable
components. The components itself are usually preceived as properties
in the consuming rust codebase.
The Architecture view
To break up the architecture of an ECS
it’s quite a help to first
define the building blocks. Here we go:
-
Entity: Is an uniquely identifyed object. The Entity can contain zero or more components.
-
Component: You are able to save datatypes inside a component. We will call the saved value of a component it’s property. The property may be looked up via its component key.
-
Entity_Component_Manager: The ECM keeps track of an entity store (bound entities and an associated component store).
-
Resource: A resource is a data slot which lives in a World. The data are shared between systems. Resources can only be accessed according to Rust’s typical borrowing model (one writer xor multiple readers). You may structure the components using resources.
-
Store: For any given storage provider the DCES defines an instance. It is quite common to utilize different, specialized stores. The store handles multiple entities, componets or resources.
-
Systems: The behaviors are processed with functions. This behavior will be processed for all matching entities of a component query.
-
World: A world represents the root of the DECS tree. Since it is totally leagal to have multiple world instances, each one represents a distinguished entity storage provider. This instances are handled via the methods of the entity_component_manager (ECM).
The following ClassDiagramms
visualizes the involved DCES
elements. To improve visibility, we will break up the complete tree into
detailed sub-trees.
classDiagram World --o EntityComponentManager World --o Resource World --o SystemStore EntityComponentManager --o EntityStore EntityComponentManager --o ComponentStore EntityComponentManager : entity_store[EntityStore] EntityComponentManager : component_store[ComponentStore] EntityComponentManager : component_store() EntityComponentManager : component_store_mut() EntityComponentManager : create_entity() EntityComponentManager : entity_counter[u32] EntityComponentManager : entity_store() EntityComponentManager : entity_store_mut() EntityComponentManager : new() EntityComponentManager : register_entity() EntityComponentManager : remove_entity() EntityComponentManager : stores() EntityComponentManager : stores_mut() Resource: FxHashMap[TypeId, Box->dyn Any] Resource : contains() Resource : get() Resource : get_mut() Resource : insert() Resource : is_empty() Resource : len() Resource : new() Resource : try_get() Resource : try_get_mut() World : entity_component_manager[EntityComponetManager] World : resources[FxHashmap] World : system_counter[u32] World : system_store[SystemStore] World : first_run bool World : create_entity() World : create_system() World : drop() World : entity_component_manager() World : from_entity_store() World : insert_resource() World : print_entity() World : register_init_system() World : resource_mut() World : remove_entity() World : run()
Next we have a look at the pieces inside the Entity hierarchy.
classDiagram Trait_EntityStore --o VecEntityStore Trait_EntityStore --o EntityBuilder VecEntityStore --o Entity EntityBuilder --o Entity EntityBuilder --o Component EntityBuilder : EntityStore[Entity, ComponentStore, EntityStore] EntityBuilder : build() EntityBuilder : components() VecEntityStore : Vec[Entity] VecEntityStore : register_entity() VecEntityStore : remove_entity() Trait_EntityStore : Entity Trait_EntityStore : register_entity() Trait_EntityStore : remove_entity() Entity : Entity[u32] Component: E[Any]
Next we present an isolated visualizaton of the Componets hierarchy.
classDiagram Trait_Component --o ComponentStore Trait_Component --o ComponentBuilder Trait_Component --o ComponentBox ComponentBox --o SharedComponentBox ComponentBox --o Component SharedComponentBox --o Component ComponentStore --o Component ComponentBuilder --o Component Component : E[Any] ComponentBuilder : ComponentBuilder[components, shared] ComponentBuilder : build() ComponentBuilder : new() ComponentBuilder : with() ComponentBuilder : with_shared() ComponentBox : ComponentBox[Box->dyn Any, TypeId] ComponentBox : consume() ComponentBox : new() ComponentStore : ComponentStore[Components, SharedComponents] ComponentStore : append() ComponentStore : entities_of_component() ComponentStore : get() ComponentStore : get_mut() ComponentStore : is() ComponentStore : is_empty() ComponentStore : is_origin() ComponentStore : len() ComponentStore : print_entity() ComponentStore : register() ComponentStore : register_box() ComponentStore : register_shared() ComponentStore : register_shared_box() ComponentStore : register_shared_box_by_source_key() ComponentStore : register_shared_by_source_key() ComponentStore : remove_entity() ComponentStore : source() ComponentStore : source_from_shared() ComponentStore : target_key() SharedComponentBox : SharedComponentBox[Entity, TypeId] SharedComponentBox : consume() SharedComponentBox : new() Trait_Component : E[Any]
Followed by the presentation of an isolated visualizaton of the System hierarchy.
classDiagram Trait_System --o SystemStore SystemStore --o SystemStoreBuilder SystemStore --o EntitySystem SystemStoreBuilder --o EntitySystem SystemStoreBuilder <-- InitSystem SystemStoreBuilder <-- CleanupSystem Trait_System : EntityStore[Any] Trait_System : run() EntitySystem: EntitySystem[Box->dyn System, priority] EntitySystem: new() SystemStore : EntityStore[entity_system->HashMap, init_system>Option, cleanup_system->Option, priorities->BTreeMap] SystemStore : borrow_cleanup_system() SystemStore : borrow_init_system() SystemStore : new() SystemStore : register_cleanup_system() SystemStore : register_init_system() SystemStore : register_priority() SystemStore : register_system() SystemStore : remove_system() SystemStoreBuilder: SystemStoreBuilder[entity_system_id, system_store, priority] SystemStoreBuilder: build() SystemStoreBuilder: with_priority()