{"id":16208781,"url":"https://github.com/starikcetin/eflatun.reflectiveecs","last_synced_at":"2025-09-11T05:05:23.881Z","repository":{"id":138987442,"uuid":"130966090","full_name":"starikcetin/Eflatun.ReflectiveECS","owner":"starikcetin","description":"A proof of concept for a reflection-based ECS system for C#.","archived":false,"fork":false,"pushed_at":"2019-06-01T02:08:52.000Z","size":62,"stargazers_count":9,"open_issues_count":0,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-28T16:58:29.055Z","etag":null,"topics":["csharp","csharp-code","ecs","entity-component-system","reflection"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/starikcetin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-25T07:16:14.000Z","updated_at":"2024-09-10T00:43:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"95e45003-cd5e-44e3-aed2-589074d53c8c","html_url":"https://github.com/starikcetin/Eflatun.ReflectiveECS","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starikcetin%2FEflatun.ReflectiveECS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starikcetin%2FEflatun.ReflectiveECS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starikcetin%2FEflatun.ReflectiveECS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starikcetin%2FEflatun.ReflectiveECS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/starikcetin","download_url":"https://codeload.github.com/starikcetin/Eflatun.ReflectiveECS/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243976478,"owners_count":20377691,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","csharp-code","ecs","entity-component-system","reflection"],"created_at":"2024-10-10T10:25:35.611Z","updated_at":"2025-03-19T08:30:51.623Z","avatar_url":"https://github.com/starikcetin.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Eflatun.ReflectiveECS\nA proof of concept for a reflection-based ECS system for C#.\n\n**This project is not complete and by no means production-ready. Use it at your own risk.**\n\n# Summary\nSystems in an ECS architecture usually fetch and filter entities/components on their own. I wanted to reverse this responsibility and design a centralized invoker that is responsible for invoking systems with the component types they want. When implemented naively, this causes double declaration of dependencies of a system, one time for the Filter object and a second time for the parameters of the execute method.\n\nTo eliminate this double-declaration and still keep the filtering responsibility away from systems, I decided to eliminate the filterer object and instead fetch the filter information from the parameters of the executer method of the System. This resulted in a syntax like this:\n\n```cs\npublic class ExampleSystem : ISystem\n{\n    [Execute]\n    public void ExecuteMethod(ComponentFoo foo, ComponentBar bar, ComponentBaz baz)\n    {\n        // system logic\n    }\n}\n```\n\nThis single method marked with `[Execute]` is all it takes to declare a system with the component dependencies.\n\nOptionally, an Execute method may take the entity itself as the first parameter (and first parameter only):\n\n```cs\npublic class ExampleSystem : ISystem\n{\n    [Execute]\n    public void ExecuteMethod(Entity entity, ComponentFoo foo, ComponentBar bar, ComponentBaz baz)\n    {\n        // system logic\n    }\n}\n```\n\nOr you can eliminate all component dependencies and write a system that runs for all existing entities, as follows:\n\n```cs\npublic class ExampleSystem : ISystem\n{\n    [Execute]\n    public void ExecuteMethod(Entity entity)\n    {\n        // system logic\n    }\n}\n```\n\n# How\nReflection! The `SystemsRunner` class uses reflection to fetch the component list of the method marked with `Execute` attribute in a system, extracts the types of these parameters and caches this information along with a delegate to invoke the `Execute` method of the said system. Afterwards, it uses this information to filter the entities that has all of the requested components and invokes the method with each of these matching entities.\n\n# Performance\n\n(comma is the fraction seperator and dot is the thousands seperator)\n\nStress testing\n```\nFrame #0 - 4263352 ticks\nFrame #1 - 4237646 ticks\nFrame #2 - 4254241 ticks\nFrame #3 - 4253610 ticks\nFrame #4 - 4216189 ticks\nFrame #5 - 4231133 ticks\nFrame #6 - 4224437 ticks\nFrame #7 - 4193977 ticks\nFrame #8 - 4213998 ticks\nFrame #9 - 4238601 ticks\nFrame #10 - 4238586 ticks\nFrame #11 - 4235248 ticks\nFrame #12 - 4200499 ticks\nFrame #13 - 4260630 ticks\nFrame #14 - 4270294 ticks\nFrame #15 - 4241092 ticks\nFrame #16 - 4226117 ticks\nFrame #17 - 4238532 ticks\nFrame #18 - 4255557 ticks\nFrame #19 - 4249101 ticks\n------------\nTotal        84.742.840 ticks\nFrame avg    4.237.142 ticks\nFPS          2,360\n\nEntities     100.000\nComp per Ent 10\nSystems      50\n\nFrames       20\n------------\n```\n\n\nA more usual setting\n```\nFrame #0 - 49635 ticks\nFrame #1 - 37129 ticks\nFrame #2 - 31091 ticks\nFrame #3 - 32160 ticks\nFrame #4 - 30094 ticks\nFrame #5 - 30926 ticks\nFrame #6 - 33303 ticks\nFrame #7 - 31246 ticks\nFrame #8 - 31481 ticks\nFrame #9 - 32152 ticks\nFrame #10 - 30982 ticks\nFrame #11 - 30294 ticks\nFrame #12 - 29921 ticks\nFrame #13 - 31116 ticks\nFrame #14 - 30549 ticks\nFrame #15 - 31595 ticks\nFrame #16 - 35947 ticks\nFrame #17 - 31617 ticks\nFrame #18 - 30950 ticks\nFrame #19 - 30700 ticks\n------------\nTotal        652.888 ticks\nFrame avg    32.644 ticks\nFPS          306,331\n\nEntities     1.000\nComp per Ent 10\nSystems      50\n\nFrames       20\n------------\n```\n\n# License\nThis project includes third party code which are not explicitly licensed. Refer to the [LICENSE NOTICE](https://github.com/starikcetin/Eflatun.ReflectiveECS/blob/master/Eflatun.ReflectiveECS.Core/Optimization/FastInvoke/LICENSE%20NOTICE) file.\n\nMIT license. Refer to the [LICENSE](https://github.com/starikcetin/Eflatun.ReflectiveECS/blob/master/LICENSE) file.\nCopyright (c) 2018 S. Tarık Çetin\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarikcetin%2Feflatun.reflectiveecs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstarikcetin%2Feflatun.reflectiveecs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarikcetin%2Feflatun.reflectiveecs/lists"}