{"id":22549067,"url":"https://github.com/dcfapixels/dragonecs-vault","last_synced_at":"2026-01-07T12:06:06.462Z","repository":{"id":232542342,"uuid":"784553733","full_name":"DCFApixels/DragonECS-Vault","owner":"DCFApixels","description":"A set of notes and code recommendations for the DragonECS framework.","archived":false,"fork":false,"pushed_at":"2024-06-13T13:25:36.000Z","size":86,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-02T10:13:47.715Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DCFApixels.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-04-10T04:34:58.000Z","updated_at":"2024-09-30T11:43:39.000Z","dependencies_parsed_at":"2024-06-13T16:01:17.795Z","dependency_job_id":null,"html_url":"https://github.com/DCFApixels/DragonECS-Vault","commit_stats":null,"previous_names":["dcfapixels/dragonecs-vault"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCFApixels%2FDragonECS-Vault","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCFApixels%2FDragonECS-Vault/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCFApixels%2FDragonECS-Vault/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DCFApixels%2FDragonECS-Vault/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DCFApixels","download_url":"https://codeload.github.com/DCFApixels/DragonECS-Vault/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246000741,"owners_count":20707781,"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":[],"created_at":"2024-12-07T16:07:48.554Z","updated_at":"2026-01-07T12:06:06.422Z","avatar_url":"https://github.com/DCFApixels.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"![image](https://github.com/DCFApixels/DragonECS-Vault/assets/99481254/3b6af524-0430-48e8-836b-7950783892b9)\n\n# DragonECS-Vault\nДанный репозитопий это сборник заметок и рекомендаций по коду для фреймворка [DragonECS](https://github.com/DCFApixels/DragonECS). \n\u003e Материал расположенный в этом репозитории не является сводом правил, не обязателен к ознакомлению, и имеет только рекомендательный характер.\n\u003e \n\u003e Местами материал может быть даже спорным, по спорным темам приглашаю вас обкашлять их в [Discord](https://discord.com/invite/kqmJjExuCf)\n\n# Стиль кода\n\nПример стиля\n```csharp\nclass ApplyVelocitySystem : IEcsRun, IEcsInject\u003cEcsDefaultWorld\u003e, IEcsInject\u003cTimeService\u003e\n{\n    class Aspect : EcsAspect\n    {\n        public EcsPool\u003cPose\u003e poses = Inc;\n        public EcsPool\u003cVelocity\u003e velocities = Inc;\n        public EcsTagPool\u003cFreezedTag\u003e freezedTags = Exc;\n    }\n\n    public void Inject(EcsDefaultWorld obj) =\u003e _world = obj;\n    public void Inject(TimeService obj) =\u003e _time = obj;\n\n    EcsDefaultWorld _world;\n    TimeService _time;\n\n    public void Run()\n    {\n        foreach (var e in _world.Where(out Aspect a))\n        {\n            a.poses.Get(e).position += a.velocities.Get(e).value * _time.DeltaTime;\n        }\n    }\n}\n```\nТот же пример, но с Auto-Injections：\n```csharp\nclass ApplyVelocitySystem : IEcsRun\n{\n    class Aspect : EcsAspect\n    {\n        public EcsPool\u003cPose\u003e poses = Inc;\n        public EcsPool\u003cVelocity\u003e velocities = Inc;\n        public EcsTagPool\u003cFreezedTag\u003e freezedTags = Exc;\n    }\n\n    [EcsInject] EcsDefaultWorld _world;\n    [EcsInject] TimeService _time;\n\n    public void Run()\n    {\n        foreach (var e in _world.Where(out Aspect a))\n        {\n            a.poses.Get(e).position += a.velocities.Get(e).value * _time.DeltaTime;\n        }\n    }\n}\n```\n\n\nНачну с объявления аспектов. Аспекты, хоть и могут использоваться одновременно несколькими системами, удобнее всего объявлять для каждой системы свои прямо внутри систем. Объявление аспекта стоит делать в самом верху системы, так удобнее читать систему, сначала идет название системы из которого можно понять что она делает, далее идет описание аспектов с которыми система работает.\n\nИменование полей в Аспектах. Поля для кеша пулов называть по названию компонента во множественном числе，например `EcsPool\u003cHealth\u003e healths`. Для этого пулы фейково реализуют IEnumerable\u003cT\u003e, чтобы автодополненте IDE предлагало такое наименование.\n\nМодификаторы доступа private/public для членов систем не имеют применения, все взаимодейсвие с системами происходит либо косвенно через данные в компонентах, а если напрямую, то через интерфейсы. Поэтому для сокращения бойлерплейта и улучшения восприятия модификаторы доступа могут быть опушены где это возможно.\n\nИменование. \n\nИменование аспектов. Многие системы работают только с одним аспектом, так что аспекты можно называть просто `Aspect`. Если аспектов несколько то основной также называть `Aspect` а второстепенный с префиксом, например `EventAspect`. \n\nИменование переменных. По той же причине что системы часто работают только с одним аспектом, возвращаемый запросом `Where` экземпляр аспекта можно называть просто `a`, а сущности внутри `foreach` просто `e`, например: `foreach(var e in _world.Where(out Aspect a)`. Аналогично именованию аспектов, если система работает с несколькими аспектами, то к `a` и `e` добавляется префикс, например: `foreach(var eventE in _world.Where(out EventAspect eventA)`.\n\n# Модули\nГруппы систем и компонетов объединенные одной логикой или реализующие некую фичу лучше ораганизовывать в модули. Модули можно рассматривать как  отедльные сборки, можно даже разбивать их на отдельные сборки.\nПапка одного модуля имеет следующую иерархию:\n```\n.../\n------+\n      | SomeModule/\n      +------+\n      |      | Components/\n      |      +------+\n      |      |      ¦ SomeComponent.cs\n      ¦      |      : IsTagged.cs\n      :      |      ·\n      ·      | Events/\n      ·      +------+\n             |      ¦ SomeEvent.cs\n             |      : SomeSignal.cs\n             |      ·\n             | Systems/\n             +------+\n             |      ¦ SomeSystem1.cs\n             |      : SomeSystem2.cs\n             |      · \n             ¦ SomeModule.cs\n             :\n             ·\n```\n+ `SomeComponent.cs` - обычные компоненты.\n+ `IsTagged.cs` - компоненты-теги которые используются просто как bool флаг, рекомендуется называть по аналогии с рекомендацией наименования bool полей, тоесть с префиксом Is.\n+ `SomeSignal.cs` - компонент-событие крепящийся к цели события.\n+ `SomeEvent.cs` - компонент-событие используемый в сущности-событие, для создания нескольких событий для одной сущности.\n+ `SomeSystem.cs` - Системы.\n+ `SomeModule.cs` - Класс реализующий интерфейс `IEcsModule`, добавляющий в пайплайн системы модуля.\n\nМодули так же удобно группировать в один надмодуль, тоесть создавать модуль который в `Import` методе просто добавляет другие модули. Например в своем проекте те модули которые могут работать независимо от Unity объединяю в модуль `ProjectCoreModule` и то что работает с Unity объединяю в `ProjectUnityModule`. Посде такого раздедения в `EcsRoot` достаточно просто добавить эти 2 модуля.\n\nДля систем и компонентов присущих одному модулю добавлять мета-атрибут MetaGroup, в качесве корневой группы использовать название модуля. Пример:\n```c#\n// Слово модуль из SomeModule будет автоматически удаленно, останется только Some\n[MetaGroup(nameof(SomeModule))]\npublic struct SomeComponent : IEcsComponent\n{\n   //...\n}\n```\nДалее можно следующей подгруппой выбрать то чем является тип, компонентом или системой. Для этого в EcsConsts есть предусмотренные константы.\n```c#\n[MetaGroup(nameof(SomeModule), EcsConsts.COMPONENTS_GROUP)]\npublic struct SomeComponent : IEcsComponent { /* ... */ }\n\n[MetaGroup(nameof(SomeModule), EcsConsts.SYSTEMS_GROUP)]\npublic class SomeSystem : IEcsRun { /* ... */ }\n```\n\n# Мульти миры\nФреймворк поддерживает создание нескольких миров и их совместную обработку в системах. Сразу оговорюсь это опциональная возможность, и если вы только начинаете свой путь в ецс или вам не удобно пользоваться этой фишкой, все можно помещать в один мир. Разделение может быть полезно с точки зрения улучшения использования памяти, группы сущностей которые по своей специфики не могут иметь общих аспектов с другими, такие сущности можно выделять в отдельные миры. Довольно типичный пример разделения миров это дефолтный мир где обрабатываются игровые сущности, и мир событий где обрабатываются сущности-события, по своей специфики у игровых и событийных сущностей редко будут пересечения аспектов, поэтому их можно выделить в отдельный мир.\n\nДля хранения  в компонентах ссылок на сущности между мирами категорически рекомендуется использовать entlong, так как у entlong есть привязка к миру. Иначе высока вероятность \"магических\" ошибок в саязи с путанницей идентификаторов.\n\n# Unchecked\nВ фреймворке некоторые методы имеют 2 версии, основную и с суффиксом Unchecked. Unchecked методы это методы которые опускают все проверки и не правильное выполнение которых может привести к нестабильному состоянию компонентов фреймворка или всего проекта. К Unchecked методам стоит относиться как к Unsafe, лучше применять только в тонких для производительности местах и если вы не уверены что делаете, лучше не использовать.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcfapixels%2Fdragonecs-vault","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdcfapixels%2Fdragonecs-vault","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdcfapixels%2Fdragonecs-vault/lists"}