Friendship ended with OOP, now ECS is my best friend
Yeah, I’m really enjoying this system of organizing my code and the fact you can just add and drop components compared to inheritance issues of OOP especially with vague and broad classes like my current project which is to make multiple types of vehicles.
My problem with OOP
Yeah with OOP you will have to worry a lot about how you are going to handle inheritance. I was thinking of one technique I saw on the scripting support forms of separating it into ObjectShared, ObjectClient, and ObjectServer but then yeah eventually it’s just not versatile enough. Like what if I want a CarClient and PlaneClient class both inherited from general VehicleClient to share the same methods for example? Yeah thinking about how to avoid this inheritance issue is a pain so I switched to ECS which yeah solves the inheritance issue entirely since it’s all components that can be split apart and recombined.
Yeah that’s my big upside from using this resource so far the organizational benefits.
However, I’ll list down some issues I found while testing the system.
- Outdated documentation.
Yeah for anyone planning to use this I recommend going to GitHub as the forum documentation is outdated with outdated syntax like:
When it has been simplified to just:
ClientSystems.testSystem = ECS.RegisterSystem()
Perhaps remove the tutorial entirely from the forum and just point towards the GitHub?
- The different work flow
Yeah this system requires a totally different work flow which takes some adjusting to especially the error messages. Here is one major one I found when I was experimenting:
Error message
--pointed to this part of the code:
if table.getn(config.RequireAny) == 0 then
error('You must enter at least one component id in the "RequireAny" field')
end
--error message:
ReplicatedStorage.Aero.Shared.ECS:129: You must enter at least one component id in the "RequireAny" field - Client - ECS:129
23:53:42.893 Stack Begin - Studio
23:53:42.893 Script 'ReplicatedStorage.Aero.Shared.ECS', Line 129 - function Filter - Studio - ECS:129
23:53:42.893 Script 'ReplicatedStorage.Aero.Shared.ECS', Line 1879 - Studio - ECS:1879
23:53:42.893 Script 'ReplicatedStorage.Aero.Shared.ECS', Line 2528 - function CleanupEnvironment - Studio - ECS:2528
23:53:42.893 Script 'ReplicatedStorage.Aero.Shared.ECS', Line 2623 - function Update - Studio - ECS:2623
23:53:42.893 Script 'ReplicatedStorage.Aero.Shared.ECS', Line 2726 - Studio - ECS:2726
23:53:42.894 Stack End - Studio
Can you guess what I did wrong from that error message if you were new to using the system?
The answer is I created an entity without any components.
local vehicleEntity = world.Create()
Yeah, I spent a frustrating amount of time wondering why this line caused an error, as I couldn’t understand at all the relationship between a component ID and why it caused an error during the update step of the world.
I guess the lesson is follow the tutorial? Anyways, please add this as an additional error message into the engine and a disclaimer in the documentation. Yeah I missed that “and” that was noted in the documentation
documentation quote:
It consists only of a unique ID and the list of components that make up this entity
The rest is mostly just syntax errors because of all the components you will need to access and require, for this, I recommend storing them all in one big table like how ECSUtil does it instead of the suggested method in the tutorial of separating each component into individual module scripts as component data is mostly just a bunch of one-liners.
And that’s it, otherwise, the documentation on GitHub was definitely well made and neat for how the API worked. For a potential improvement, I would swap out weapons for the System improvements:
OnRemove = function(time, world, entity, index, weapons)
-- on new entity
print('Entity removed ', entity)
return false
end,
as weapons should have represented the component_N_data instead, so I guess it should have been left as a variadic function to represent … the general case of what the additional parameters are returning.
Also the outdated API here for system config caused an error once
-- [Optional] Invoked before executing the update method
BeforeUpdate = function(time, interpolation, world, system)
-- called before update
print(system.config.customConfig)
end,
Yeah overall, a really great resource that works. Just could be a little more user friendly with the documentation
Here’s a really minor pull request to fix the error readability for newer users who don’t like to read documentation
Am I doing it correctly?