Skip to main content

xgaida-x-nixi-data-authoring

Дата-слой Guildmaster: авторинг контента и конфигов — три слоя SO→POCO→DTO, строковые id domain.name, ScriptableObject-определения (UnitData, RelicData, EffectData и родня), стат-блоки и StatsConfig, реестр контента, лок-ключи, валидация и контракты сериализации. Зови на любую работу с данными и всё под Assets/_Project/Scripts/Data и ScriptableObjects. НЕ применять к: ПОВЕДЕНИЮ эффектов и боевой логике (combat-sim — здесь только определение), окну Content Hub, дизайн-тексту ГДД (gdd-scribe), рантайм-UI (uitk).

Jump to install

Source facts

Repository
Kaliguri/Guildmaster-Autobattler
Last source activity
August 7, 2026 at 10:28
Detected SKILL.md language
Russian
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
5 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
xgaida-x-nixi-data-authoring
description
Дата-слой Guildmaster: авторинг контента и конфигов — три слоя SO→POCO→DTO, строковые id domain.name, ScriptableObject-определения (UnitData, RelicData, EffectData и родня), стат-блоки и StatsConfig, реестр контента, лок-ключи, валидация и контракты сериализации. Зови на любую работу с данными и всё под Assets/_Project/Scripts/Data и ScriptableObjects. НЕ применять к: ПОВЕДЕНИЮ эффектов и боевой логике (combat-sim — здесь только определение), окну Content Hub, дизайн-тексту ГДД (gdd-scribe), рантайм-UI (uitk).
# Data Authoring — рабочий контур Guildmaster Этот скилл — процедура, а не справка. Он превращает правила дата-слоя в чеклист, который прогоняется на КАЖДОЙ задаче с контентом. Цель — чтобы весь игровой контент жил в трёх чётких слоях, связывался стабильными строковыми id, проходил валидацию и не тянул за собой запрещённые практики сериализации, а новый контент ложился в готовые контракты (`ContentDefinition`, `ContentDomains`, `IContentDatabase`), а не рядом с ними. ## Прежде всего: карта дата-слоя Каркас уже построен и покрыт EditMode-тестами. Ничего не изобретай — читай, продолжай, встраивайся в существующие швы. | Что | Где | |---|---| | Базовый класс контент-SO (id `domain.name`, Edit Id) | `Assets/_Project/Scripts/Data/Definitions/ContentDefinition.cs` | | Маппинг тип→домен + генерация id из имени | `Assets/_Project/Scripts/Data/Definitions/ContentDomains.cs` | | Боевой кит юнита (база всего на арене) | `Assets/_Project/Scripts/Data/Definitions/UnitData.cs` | | Реликвия игрока / враг (мета над китом) | `.../Definitions/RelicData.cs`, `.../Definitions/EnemyData.cs` | | Прочие контент-типы (эффект/предмет/сосуд/энкаунтер/ивент…) | `Assets/_Project/Scripts/Data/Definitions/*.cs` | | Стат-модификатор / список статов / операции | `Assets/_Project/Scripts/Data/Stats/StatModifier.cs`, `StatType.cs`, `ModifierOp.cs` | | Глобальный шаблон статов (дефолты + константы) | `Assets/_Project/Scripts/Data/Definitions/StatsConfig.cs` | | Реестр контента (шов код↔контент) | `.../Definitions/IContentDatabase.cs`, `ContentRegistry.cs`, `ContentDatabase.cs` | | Лок-мост «контент ↔ String Table Content» | `Assets/_Project/Scripts/Data/Editor/ContentLocalization.cs` | | id-утилиты / поиск ассетов (editor) | `Assets/_Project/Scripts/Data/Editor/ContentIdUtility.cs` | | Массовая правка ассетов (Undo + аудит + обратный пресет) | `Assets/_Project/Scripts/Data/Editor/ContentEditService.cs`, `ContentEditBatch.cs`, `ContentCrudService.cs` | | Валидация контента (id/дубли/null-ref) | `Assets/_Project/Scripts/EditorTools/ContentHub/Core/ContentValidationService.cs` | | Тесты контента (EditMode) | `Assets/_Project/Tests/EditMode/Content/*.cs`, `.../ContentHub/*.cs` | | Сами ассеты контента | `Assets/_Project/ScriptableObjects/**` | | Канон дизайна дата-слоя | `docs/wiki/tech/13. Дата-слой и контент-каркас (SO и конфиги).md` | **Слои (asmdef) — зависимость строго вниз:** `Core ← Data ← Combat`. `Guildmaster.Data` не тянет `Combat`/`Presentation`/движковую презентацию. Контент-SO — чистые данные; логика (сборка юнита, тик, эффекты) живёт в `Combat` и читает данные, а не наоборот. ## Три слоя данных (держать в голове всегда) 1. **SO (авторинг).** `ScriptableObject`-определения (`ContentDefinition` и наследники). Иммутабельны в рантайме. Их правит человек/инструмент в редакторе. 2. **Baked POCO (сим).** Чистый C#, снятый со снапшота SO на старте боя. С ним работает симуляция — детерминированно, без обращения к ассетам. 3. **DTO (сейвы/реплеи/Workshop).** Плоская сериализуемая форма для диска и сети. Ссылки между слоями — ТОЛЬКО строковый id `domain.name`, никогда прямой object-ссылкой. Скилл владеет **контрактами** всех трёх слоёв. Реализация сим-POCO — на стороне `combat-sim`; плумбинг сейв/загрузки (свой `JsonFileSaveService` за `ISaveService`) — будущий `save-system`. Здесь — форма и id-дисциплина. ## Шесть правил, нарушение которых = переделка (HARD) Каждое закрывает конкретный способ, которым дата-слой незаметно загнивает. Пойми «почему» — тогда не придётся заучивать «нельзя». 1. **Связь слоёв — только строковый id `domain.name`; SO не мутируется в рантайме.** POCO/DTO ссылаются на контент по id, а не прямой object-ссылкой. SO — иммутабельный источник; менять его значения в игре нельзя (кроме осознанного live-тюнинга в play mode, см. `references/stats-and-configs.md`). *Почему:* id переживает пересборку, сеть и Workshop; прямые ссылки в POCO/DTO ломают детерминизм и сейвы. Мутация SO в рантайме — молчаливая порча общего источника. 2. **Запрещено навсегда:** Odin **Serializer** (`SerializedScriptableObject` — blob, AOT, конфликты netcode/Workshop); `AnimationCurve.Evaluate` из тика сима (кривые бейкаются в таблицы); `Resources.Load`/статик-доступ к конфигам; тихий code-fallback при отсутствующем конфиге (`config == null ? 5f` — падать громко при композиции, не подставлять число). *Почему:* каждый пункт — прецедент конкретного бага (потеря данных, недетерминизм, невидимая зависимость, «работало на дефолте, сломалось на реальных данных»). *Граница:* Odin **Inspector** (type-picker для `[SerializeReference]`, атрибуты `LabelText/Button/EnableIf`) — РАЗРЕШЁН, это удобство инспектора. Запрещён только Serializer. 3. **id генерируется и лочится.** `domain.name`, где `domain` — из ЗАКРЫТОГО словаря `ContentDomains` (новый тип → сперва зарегистрировать домен), `name` — `lower_snake` из имени ассета (авто через `OnValidate`). После выхода контента «в мир» (сейвы/реплеи/Workshop) id НЕ меняется; правка — только через кнопку **Edit Id** с предупреждением. *Почему:* id — стабильная идентичность. Меняешь id вышедшего контента — рвёшь чужие сейвы и реплеи. Rename ассета не должен трогать id (потому синхронизация имя→id одноразовая). 4. **Весь доступ к контенту — через `IContentDatabase`.** Геймплей берёт определения только из реестра (`Get<T>(id)` / `TryGet` / `All<T>`), зарегистрированного в DI. Никаких прямых SO-ссылок из логики и `Resources.Load`. *Почему:* реестр — единственный шов код↔контент. Он же — точка, куда позже сядут source-namespace под моды и addressable-загрузка (см. `references/localization-and-loading.md`). *Готча:* новый контент-SO не виден геймплею, пока не прогнан `Tools/Guildmaster/Sync Content Database` (в скрипте — `ContentDatabaseSync.Sync`). Симптом выглядит как «id не найден», хотя ассет на диске есть. Прямая ссылка в обход реестра убивает этот шов. 5. **Весь player-facing текст — лок-ключами, RU заполняем, прочие локали прочерк.** Ключи `{id}.name`/`{id}.desc` (+ спец-суффиксы, см. политику в `ContentLocalization`) в String Table `Content`. Текст в SO НЕ хранить — заводить/править ключи editor-хелпером. *Почему:* заложить локализацию сразу дёшево, ретрофитить — дорого. Прямая строка в SO = откат к нелокализуемому тексту. 6. **`[MovedFrom]` / `[FormerlySerializedAs]`-дисциплина.** Rename/перенос типа под `[SerializeReference]` — только с `[MovedFrom]`; переименование сериализованного поля — только с `[FormerlySerializedAs]`; перенос поля в базовый класс безопасен при сохранении имени. *Почему:* Unity матчит сериализацию по именам. Молчаливый rename обнуляет данные в сотнях ассетов без ошибки компиляции. **Плюс сквозной инвариант (тоже HARD): значения — из данных/конфигов, не хардкод.** Тюнеры и статы живут в ассетах (`StatsConfig`, стат-блок SO), а не в инициализаторах полей и не магическими числами в коде. Дефолт живёт в `.asset`, а не в инициализаторе (правка инициализатора НЕ обновляет существующие ассеты). ## Границы со смежными скиллами Дата-слой стыкуется со многими контурами — режем чётко, на стыке взаимная ссылка, а не спор. - **combat-sim (эффект живёт на два дома).** data-authoring владеет ОПРЕДЕЛЕНИЕМ: `EffectData` SO, `id`, баланс-цифры, состав компонентов через `[SerializeReference]`, loc. combat-sim владеет ПОВЕДЕНИЕМ: логика `IRuntimeEffectComponent`, тик, стакинг-механика, реактивы. Задача «новый эффект» трогает оба — определение здесь, поведение там. - **content-hub (будущий скилл).** Редакторное ОКНО `ContentHubWindow` (уже написано на чистом UITK) — контур content-hub. data-authoring владеет КОНТРАКТАМИ данных, которые окно правит, и инвариантами валидации. Окно не перестраиваем — используем как инструмент авторинга. - **save-system (будущий скилл).** data-authoring держит форму DTO (id-ссылки, `schemaVersion`, `[MovedFrom]`-дисциплина). Плумбинг сейв/загрузки (свой бэкенд на Newtonsoft, Steam Auto-Cloud, миграции сейвов) — контур save-system. - **gdd-scribe.** Там — дизайн-ТЕКСТ (карточки, баланс-намерение, термины). Здесь — ДАННЫЕ, реализующие этот дизайн. Числа в ассете ≠ дизайн-решение в ГДД. - **uitk / gamefeel-vfx.** Визуальные ссылки (иконки, `viewPrefab`, `AnimationArchetypeData`) авторятся здесь как поля SO, но их отрисовку/полиш держат UI/визуальные скиллы. ## Как я авторю данные — ГИБРИД (файл + проверка через MCP) 1. **Пишу C#-типы SO напрямую** (`Write`/`Edit`) — контролирую код и его слой (asmdef `Data`, зависимость строго вниз). 2. **Новый контент-тип →** регистрирую домен в `ContentDomains`, добавляю в реестр (`ContentDatabase`), завожу инвариант в валидации/тестах. 3. **После C#-правок — `read_console`** (Unity MCP): дождаться компиляции, ноль ошибок, только потом использовать новые типы. 4. **Ассеты** создаю через `CreateAssetMenu`/Content Hub; id авто-заполняется из имени; лок-ключи завожу `ContentLocalization` (create-missing-keys), значения статов — в ассете. 5. **Массовая правка существующих ассетов** — editor-миграцией (образец `Migrations/`), не руками по одному и не hand-YAML (Unity перезапишет). 6. **Перед «готово» — `run_tests`** по Content/ContentHub-подмножеству; полный прогон — CI. ## Чеклист сдачи задачи с данными Прогнать перед тем, как сказать «готово»: - [ ] Связь слоёв — по id; SO в рантайме не мутируется; POCO/DTO не держат прямых object-ссылок - [ ] Ноль запрещённых практик: нет Odin Serializer, curve-eval в тике, `Resources.Load`, тихого code-fallback при null-конфиге - [ ] Новый контент-тип: домен в `ContentDomains`, регистрация в реестре, инвариант в валидации - [ ] id формата `domain.name`, домен под тип, уникален; не менял id вышедшего «в мир» контента - [ ] Доступ к контенту — только через `IContentDatabase`, не прямой ссылкой / `Resources.Load` - [ ] Player-facing текст — лок-ключами (RU заполнен, прочие прочерк); текста в SO нет - [ ] Rename типа/поля — с `[MovedFrom]`/`[FormerlySerializedAs]` - [ ] Значения — в ассетах/конфигах, не хардкод; дефолт в `.asset`, не в инициализаторе - [ ] `read_console` чист (компиляция); `run_tests` по Content зелёный - [ ] Массовые правки ассетов — миграцией, не руками ## Справочные файлы (читать по надобности) - `references/three-layers-and-ids.md` — три слоя SO→POCO→DTO, `ContentDefinition`, жизненный цикл id и `ContentDomains`, реестр `IContentDatabase`/`ContentRegistry`, source-namespace шов под моды, `[MovedFrom]`-дисциплина. Читать перед созданием нового контент-типа. - `references/stats-and-configs.md` — `StatType`/`StatModifier`/`ModifierOp`, авторинг базы через `Override`, `StatsConfig`, формула сборки, конфиг-бейк/снапшот/tainted, запрет curve-eval, анти-хардкод. Читать перед правкой статов или конфигов. - `references/localization-and-loading.md` — лок-ключи `{id}.suffix`, политика обязательных суффиксов по доменам, `ContentLocalization`-хелпер, RU-only, Addressables только под Loc, прямые ссылки на контент, триггеры пересмотра под моды. Читать перед правкой текста/загрузки. - `references/validation-and-authoring.md` — инварианты валидации, `ContentValidationService`, связь с Content Hub, Odin-в-инспекторе, процедура авторинга ассета, editor-миграции. Читать перед заведением валидации или массовой правкой ассетов.
View on GitHub