I have been reading a lot about different design patterns, their pros, cons, main usage etc. However, I like to experiment and try to invent my own ways of the implementations (even if they are not the best). Now I am facing a problem with my Entity component system implementation.
Despite of the pros of this pattern I want to do some of the things in my own way, for example:
1.) Components are wrapped into bigger interfaces for data manipulation. In most of the cases i read that ECS components must contain only data and the systems are their main manipulators. In my system I intend to use a wrapper classes for the components
Little example: Lets say we want to have a Sprite component, that represents the visual component of each entity in game. I wrapped it inside the RenderableEntity class that can be a component of an entity and has additional functions and variables.
2.) I don´t use a system for every type of component.
Again an example from game engine : We have a CollidableEntity, that is put in some spatial data structure and doing its collision checks, but for RenderableEntity there is no system that manages it (I assume that we are in 2D now). Reason? I want the user to have the power of rendering the sprites of each entities, because of specific order or using different batches.
3.) Entities can have more than 1 component of the same type and no bitsets are used for checking if is the system interested in given entity. The components are assigned to systems at their creation via the data type.
Little code:
template<class DataType>
DataType* createComponent(GameEntity* mainEntity)
{
//Create it via default constructor
DataType* component = new DataType();
//Add it to the back of the component vector
mainEntity->_entityComponents.emplace_back(component);
//Assign it to system
ECS::assignToSystem<T>(component);
//Return it to access its functions
return component;
}
The assignToSystem function does following : checks if is the given data type in our map and if not, it adds the component to the system and from now is the system the maintainer of the component. Also the gamesystems are attached to given data types via a function and it looks like this :
class ColliderSystem:public ECS::System
{
void assignSystem() override
{
ECS::assignSystemToComponent<CollidableEntity>(this);
}
};
Can you tell me if its a good idea to experiment with given patterns and try to do things your own way? Especially I care about this because want to use this approach in my graduation work and wonder if it will be a problem if I "break rules" of some patterns. Also , what do you think about my "changes", are there any cons? Thanks.
Best Answer
People have experimented with different mechanics of implementing a design pattern in the past with differing results. For example, the definition of a singleton is that there is only one instance of a class for your entire application. There is nothing in that definition that requires you to implement it with a static accessor, even though that's how the example in the GoF book is written. Folks that use components like the Spring framework let the component container guarantee that there is only one instance and a reference to that instance is injected everywhere you need access.
That example leads to a few points:
At the end of the day, no user is going to praise your judicious use of the flyweight pattern or even know that you used a decorator pattern in there somewhere. Patterns are called that because they are common solutions to common problems that happen to have very similar implementations. Many times the details of the implementation are less important than the concept that inspired it. Just make sure that your code is comprehensible to someone else, or even your future self 3 months down the road.
I'm not going to get preachy, but I will encourage you to look at the impact of what you are doing as objectively as you can. Users only care that the application/game/tool/etc. works. Developers on your team care about whether they can understand it and fix it when they find things that are broken. Every time you deviate from the norm, it increases the amount of time it takes to understand the code. Make it annoying enough and your development team will rewrite everything so that it is more familiar.