T
T
toster_bodnar2021-04-28 09:57:28
C++ / C#
toster_bodnar, 2021-04-28 09:57:28

How to organize Tween system within ECS (entt)?

There was a need for a tween system for the game. Almost all logic in the game is tied to ecs. I am using the entt library.
The idea came up as follows: I made a component with data about twin.

struct TweenComponent
{
    EasingType type;
    float delay;
    float fromValue;
    float toValue;
    float duration;
};


And I threw in an approximate part of the system that will process the entities on which the component was hung.
void update(entt::registry& registry, float dt)
{
    auto view = registry.view<TweenComponent>();
    for(auto entity: view)
    {
        auto tween = registry.get<TweenComponent>(entity);
        ...
    }
}


Where there is an ellipsis, I planned to implement the logic for changing the parameter depending on the interpolation function that is selected in the component. But here is just a misunderstanding. How to universally make the transfer through the component of the desired parameter, to which the twin animation will be applied? And immediately there was a problem with the fact that we can only hang one TweenComponent on an entity. But what about the fact that you will need to animate several parameters at once (for example, position and color)? In general, such an architecture for using tween animation is somehow not very good ..
Maybe someone knows how best to implement this system within ecs?

There were thoughts to make for each entity parameter that needs to be animated, its own tween component (PositionTweenComponent, ColorTweenComponent). And then in the system to make selections for entities of each type. So we will immediately understand which parameter to get from which component.
There were also ideas to pass a certain handle to TweenComponent as one of the parameters, in which to describe the necessary actions on the necessary parameter of other components. In general, tell me please, how is it done?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Evgeny Shatunov, 2021-04-28
@toster_bodnar

In this case, one component and one system is not enough. When an arbitrary number of other components are affected, linking them all to any one component is like burying the ECS back into the ground.
Why single component design is doomed. Every system in the ECS must work with component sampling. In EnTT, this is done using the component flow representation - entt::registry::view.
Such a representation optimally organizes a sequence of entities that exactly contain the components indicated in the representation. If you start checking for the presence of other components in an entity, in addition to being contrary to the concept of ECS, this will affect fetching from memory outside the map and greatly reduce system performance. Therefore, the system should not work with components outside of its selection.
By design, you want to make a system that will interpolate arbitrary values ​​of arbitrary fields of arbitrary components using the data of one particular component. Such a design will only lead you to the fact that in this system you will have to make a selection for all components, which, in fact, will make this system dysfunctional. This is simply because not all entities, the values ​​of whose components you want to interpolate, will have all the other components, the values ​​of which the system can also interpolate.
How to be in that case. You need to isolate functionality into more local systems instead of one big interpolation system. Here you have an entity color component - ColorComponent, and you can interpolate this color. So you need a color interpolation component -ColorInterpolationComponent. In this interpolation component, you need to define the interpolation law, the initial and final values, as well as the interpolation time. ColorInterpolationComponentsays that all data is ColorComponentinterpolated according to a certain law between certain values ​​​​and for a certain time.
Your interpolation functions are always clean, i.e. depend only on the arguments passed to them. For any data type, from scalar to matrix, you can define an interpolation function between two values. These are all things external to the ECS, and inside the ECS ***InterpolationComponentyou will have your own system for each, which makes a selection by the target component and by the interpolation component. Thus, already at the stage of selecting components, you will have only suitable entities, and all the rest will be filtered out.
It is also worth noting that this approach allows one specific value to be interpolated by only one function at a time. If multiple simultaneous interpolations are required for a single value, this approach is no longer suitable. On the other hand, in order to correctly converge several such animations for a single value, a much more complex system is required than a simple interpolation function.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question