Skip to main content

xgaida-x-nixi-gamefeel-vfx

Джус и визуальный фидбэк Guildmaster: политика значимости (что достойно slowmo и тряски), per-hit фидбэк (hitstop, вспышка, сплющивание, боевые цифры), VFX, death-shatter, screen shake за IScreenShake, feel-конфиги и шов префаб-VFX (SO→префаб→пул→сокет). Зови на любую задачу про сочность, VFX, тряску, замедление, партиклы и всё под Presentation-визуалом. НЕ применять к: боевому времени и его контракту (combat-sim — здесь только потребитель), звуку (audio), определениям VfxData как контента (data-authoring).

インストールへ移動

ソース情報

リポジトリ
Kaliguri/Guildmaster-Autobattler
ソースの最終更新活動
2026年8月7日 02:38
検出された SKILL.md の言語
ロシア語
スター
0
フォーク
0

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
4 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
xgaida-x-nixi-gamefeel-vfx
description
Джус и визуальный фидбэк Guildmaster: политика значимости (что достойно slowmo и тряски), per-hit фидбэк (hitstop, вспышка, сплющивание, боевые цифры), VFX, death-shatter, screen shake за IScreenShake, feel-конфиги и шов префаб-VFX (SO→префаб→пул→сокет). Зови на любую задачу про сочность, VFX, тряску, замедление, партиклы и всё под Presentation-визуалом. НЕ применять к: боевому времени и его контракту (combat-sim — здесь только потребитель), звуку (audio), определениям VfxData как контента (data-authoring).
# Gamefeel & VFX — рабочий контур Guildmaster Этот скилл — процедура, а не справка. Он превращает разрозненные правила «сочности» в чеклист, который прогоняется на КАЖДОЙ фидбэк-задаче. Цель — чтобы джус и VFX оставались развязанными от боевого ядра (смотрят на sim, не мутируют его), data-driven (значения и формы — в SO, эффекты — в префабах), а новый фидбэк ложился в готовые швы, а не рядом с ними. **Роль на этом слое:** я держу КОНТРАКТ фидбэка (кто на что подписан, где живёт global-feel, как эффект попадает на экран, какие швы). Визуальную приёмку и полиш — как именно выглядит бёрст, кривая шейка, тайминг «на глаз», сам арт — делает Макс. Я кручу визуал-параметры только по его ТЗ и показываю результат. ## Дизайн-документация джуса — тоже мой контур (решено 2026-07-31) **Кластер `docs/wiki/gdd/70-gamefeel/` принадлежит этому скиллу, а не `gdd-scribe`.** Писарь ГДД владеет чистым геймдизайном — механиками, балансом, контентом; в джусе дизайн и реализация неотделимы (тайминг эффекта — одновременно дизайн-решение и число в конфиге), и разводить их по двум скиллам значило бы развести один факт по двум головам. Прецедент — `narrative` с `60-narrative`. | Файл кластера | Что держит | |---|---| | `vfx-language.md` | **как выглядит событие**: роли-слои, тайминги, масштаб в долях роста юнита, словарь боевых событий | | `vfx-color.md` | чем красим: главный цвет и палитра разброса, роли оттенков ростера | | `asset-palette.md` | чем рисуем: связка «роль → текстура». **Не инвентарь ассетов** — тот живёт в `tech/10-reference/asset-inventory` | | `backlog-gamefeel.md`, `backlog-vfx-particles-shaders.md` | банки идей: тактильный слой и визуальный | Правила ведения те же, что у остальной ГДД: принятое решение — записью в `gdd/00-meta/journal-adr.md` с датой и причиной (append-only, старое помечается `superseded`); своё предложение — только как `proposed`; после правки прогнать оба гейта — `check-wiki-frontmatter.ps1` и `check-wiki-links.ps1`. **Эффект, показанный в бою, обязан иметь строку в словаре событий** (`vfx-language.md`). Не имеет — значит его форму никто не выбирал, и следующий заход соберёт её заново по-своему. ## Модель боевого удара — принята 31.07.2026, читать ПЕРЕД любым разговором о формах Канон целиком — `docs/wiki/gdd/70-gamefeel/vfx-language.md`; здесь только то, без чего разговор начнётся с нуля. **Терминология обязательна к использованию** (заведена по жалобе Макса «терминов нет норм, путаюсь»). **Термины:** **форма** (серп / веретено / звезда) · **ядро** (радиальная вспышка, параметр — радиус) · **искры** (частицы прочь) · **порез** (красная метка на теле, накапливается) · **остаток** (пыль, след) · **дуга за клинком** (VFX-сектор от плеча на взмахе) · **A** (начало взмаха, маркер `StrikeStart` как геометрия) · **B** (точка попадания, маркер `Hit`). Слово «разрез» изъято. **Две стадии, и они в разное время — поэтому не конфликтуют:** | Стадия | Что | Когда | |---|---|---| | 1 · взмах | **дуга за клинком** — сектор от плеча, заметающий пройденный угол | strike-фаза, до хита | | 2 · хит | **серп** A→B, **ядро**, **искры**, **порез** | от кадра `Hit` | **Семь правил, которые ломаются легче всего:** 1. **Форма строится по ДВУМ ТОЧКАМ (A→B), а не по траектории клипа.** Точка хита — **середина** формы у серпа и веретена (клинок проходит навылет), **конец** у звезды-дробящего. 2. **Нет контакта — нет серпа.** На промахе: дуга есть, серпа/ядра/искр/пореза нет, только «evade». Дуга рисуется на каждом взмахе — она говорит «клинок прошёл здесь», и это правда даже при промахе. 3. **Три архетипа — это ПРАВИЛА ГЕНЕРАЦИИ, а не три готовых знака.** Процедурно гуляют прогиб, толщина в коридоре, неровность, лучи звезды. **Размер не гуляет** — он несёт урон. 4. **Форма говорит КАК доставили, цвет говорит ЧЕМ ударили.** Отдельных форм под элементы нет и не будет: элемент несёт палитра юнита. Дальний бой — линия-всполох, тот же колющий с нулевым прогибом, после хита, по вектору снаряда. 5. **Всё рисуем сами шейдером на одном quad (SDF).** Спрайтовые листы эффектов — не наш путь: форма параметрическая, потому что настраивается данными, а не перерисовывается. Пиксель-арт отменён (`2026-08-01/14`), юнит теперь плоский сторибук — эффект и юнит в одной гладкости, а различает их яркость. 6. **Порез — это СОСТОЯНИЕ тела** (`BodyVisualState` через `IUnitBodyVisual`), не событие. Лимит 12, позиции из `IRngService`, хил гасит **самые старые** пропорционально их запасу HP. 7. **Количество и размер — пропорция урону с ПОТОЛКОМ.** Категорий «лёгкий/тяжёлый» нет. Искры: `6 + доля_HP × 120`, не больше 48. Форма замирает вместе с hitstop. **Живой стенд — `docs/gamefeel-demos/index.html`**, растущий одностраничник: показывает всё это в движении на настоящем тайминге 30 Гц. Новая тема — новый раздел; после вердикта в разделе обязан появиться стенд «принято». Правила ведения — `docs/gamefeel-demos/README.md`. ## Прежде всего: карта фидбэк-слоя Слой уже построен и живёт в презентации. Ничего не изобретай — читай, продолжай, встраивайся в существующие швы. | Что | Где | |---|---| | Режиссёр значимости (global-feel: kill-slowmo, heavy-shake, финишер) | `Assets/_Project/Scripts/Game/Services/CombatFeelDirector.cs` | | Мост sim→presentation + per-hit фидбэк (hitstop, цифры, спавн VFX) | `Assets/_Project/Scripts/Presentation/CombatPresenter.cs` | | Тряска камеры за интерфейсом | `Assets/_Project/Scripts/Presentation/Camera/IScreenShake.cs`, `ScreenShake.cs` (Cinemachine-extension). Регистрация — `WorldLifetimeScope`; заглушки нет и не заводим | | Пул + спавн VFX-префабов (ключ пула — `EntityId`) | `Assets/_Project/Scripts/Presentation/CombatVfx.cs`, `PooledVfx.cs` | | Определение VFX (префаб, sorting, дефолт-направление) | `Assets/_Project/Scripts/Data/Definitions/VfxData.cs` — владеет `data-authoring` | | Разлёт спрайта на осколки при смерти | `Assets/_Project/Scripts/Presentation/DeathShatter.cs`, `ShatterMesh.cs` | | Всплывающие боевые цифры (урон/хил/evade) | `Assets/_Project/Scripts/Presentation/FloatingText.cs` | | Вспышка арены/фон | `Assets/_Project/Scripts/Presentation/CombatAreaFlash.cs` | | Вид юнита: вспышка/сплющивание/hitstop/death-хуки, точки-сокеты | `Assets/_Project/Scripts/Presentation/UnitView.cs`, `UnitAnimation.cs` | | Единый feel-конфиг (impact-параметры, тумблеры `Enable*`) | `Assets/_Project/Scripts/Presentation/Design/CombatFeelConfig.cs` | | Палитра боевого UI | `Assets/_Project/Scripts/Presentation/Design/CombatColorPalette.cs` | | Боевое время (ПОТРЕБЛЯЕМ, не владеем) — slowmo/пауза/скорость | `Assets/_Project/Scripts/Game/Services/TimeScaleService.cs` → скилл `combat-sim` | **Слой (asmdef):** всё это — `Guildmaster.Presentation` (визуал-компоненты) и `Guildmaster.Game` (сервисы-режиссёры, сшивка через VContainer + MessagePipe). `Presentation` ссылается на `Combat` и СМОТРИТ на него; `Combat` на презентацию не смотрит НИКОГДА. `CombatFeelDirector` живёт в `Game`, потому что ему нужны и `CombatSimulation` (события), и `TimeScaleService`/`IScreenShake` — их `Presentation` не тянет (иначе цикл asmdef). ## Четыре правила, нарушение которых = переделка (HARD) Каждое закрывает конкретный способ, которым фидбэк незаметно загнивает. Пойми «почему» — тогда не придётся заучивать «нельзя». 1. **Все VFX — префабы. И точка.** Конечная форма любого боевого VFX (партиклы / VFX Graph / ShaderGraph-материал) — самодостаточный префаб, лежащий ссылкой в SO, который презентер спавнит в мировой точке-сокете через `ObjectPool` по боевому событию. Эталон уже в проекте: `UnitData.ViewPrefab` — «визуал/анимация/размер настроены ПРЯМО в нём, префаб самодостаточен» (`CombatPresenter.HandleUnitSpawned`). Так же спавнятся `_bulletPrefab`, `_floatingTextPrefab`. *Почему:* префаб — единственная форма, где художник собирает эффект без кода, а код про эффект знает ровно одно: «заспавнить в точке». Кодовый меш плодит визуал в C#, который нельзя приёмить глазами и нельзя отдать художнику. *Где код остаётся законно:* `DeathShatter`/`ShatterMesh` (меш режется из спрайта конкретного юнита — префабом не подменить) и dev-слой `CombatStatusOverlay`. `PixelBurst*` удалён. Новый эффект кодовым мешем не делаем даже «на время». *Шов* (`VfxData` SO → префаб → `CombatVfx`-пул → сокет) **построен** — им и пользуемся, см. раздел ниже и `references/vfx-and-pooling.md`. 2. **Global-feel только в `CombatFeelDirector`; per-hit — в презентере.** Глобальные эффекты значимости (kill-slowmo, heavy-shake, финишер-таймлайн, тряска) решает ОДНО место — `CombatFeelDirector`, по политике «что достойно момента». Точечный фидбэк пары «источник+цель» (hitstop, вспышка, сплющивание, искры, цифры) — в `CombatPresenter`. Не размазывай глобальный feel по `UnitView` и не дёргай глобальную тряску/время из точечного фидбэка. *Почему:* значимость — это политика («килл щёлкает, царапина нет»). Размажешь по вьюхам — потеряешь единую точку, где её крутят, и получишь slowmo на каждый тик DoT. 3. **Значения и формы — из feel-SO, не хардкод.** Тайминги, факторы, кривые — в `CombatFeelConfig` (+ `VfxData` для префабных эффектов). Потребители тянут значения ОТТУДА (`UnitView`, `CombatPresenter`, `ScreenShake`, `CombatFeelDirector`), а не из чисел в коде. Крутить фидбэк = править SO. *Почему:* джус настраивается итерациями «на глаз» — это работа Макса в инспекторе. Число в коде = правка кода на каждый чих баланса фидбэка и недоступно дизайнеру. **ЦВЕТ — исключение: он живёт НЕ в feel-SO** (с 30.07.2026). Ни `CombatFeelConfig`, ни `CombatColorPalette` не хранят `Color` — они называют роли `--gm-color-combat-*`, значения лежат в `UI/Theme/tokens.*.uss` → снимок `GuildmasterPalette` (пересобрать: Alebardium → Дизайн-система). HDR туда не едет: в палитре LDR-база, силу свечения задают числа-множители в конфиге (осколки ×2.75, вспышка смерти ×1.8 — один оттенок пересвета, два события). Новый цвет фидбэка = ступень в примитивах + роль в семантике + пересборка снимка + имя роли в `PaletteSnapshotTests`. Заводить `Color`-поле в конфиге — прямой откат: семь таких полей уже дублировали токены и совпадали только потому, что их никто не правил. 4. **Presentation читает sim только через события/MessagePipe и не влияет на детерминизм.** Фидбэк СМОТРИТ на бой: подписка на C#-события `CombatSimulation` (презентер) или на MessagePipe (`CombatFeelDirector`, как `AudioPresenter`). Никогда не пишет в `RuntimeUnit`/sim и ничего не решает за бой. Всё визуальное живёт на `Time.deltaTime`/твинах/unscaled, не на sim-тике. *Почему:* как только фидбэк мутирует мир или влияет на порядок тика — рушится и детерминизм (кооп-checksum), и headless-тестируемость боя. Это инвариант `combat-sim`, здесь он в силе как граница. **Плюс два инварианта реестра (30.07, заказ Макса «чтобы ни о ком не забыть»):** 5. **У КАЖДОГО эффекта есть выключатель, и он один по форме.** Тумблер `Enable*` в `CombatFeelConfig`; длительность настраивает, а не выключает. До правки джус выключался четырьмя разными способами, а пять эффектов (вспышка удара, сплющивание, вспышка телеграфа, поза гвардии, разлёт на осколки) не выключались вовсе — «список тумблеров» отвечал на вопрос «всё ли включено» неправдой. 6. **Перепись живёт в тесте, а не в SO.** `FeelToggleCoverageTests` держит таблицу «вход → чем выключается» и роняет сборку, если появился новый `Play*`/`Show*`/`Raise*` без записи. Отдельный SO-список стал бы вторым владельцем факта и разошёлся бы с кодом на первом же эффекте; перепись в тесте расходиться не умеет — она падает. *Самая ценная проверка там — текстовая:* тумблер обязан ЧИТАТЬСЯ в коде презентации. Рефлексия этого не видит (свойство существует и возвращает значение, даже если его никто не спрашивает), а именно так выглядит «завели ручку и забыли подключить». *Законное исключение:* тумблер, применяемый ВНУТРИ конфига (цвет вспышки по школе) — он наружу не торчит и помечен в переписи отдельным видом. ## Проверка «дружит ли с новой презентацией юнита» (30.07) Скелетный юнит — не один спрайт, поэтому вопрос «работает ли фидбэк» разбивается на четыре, и все проверяются без play-mode: - **Материальное — только через шов** `IUnitBodyVisual` (тинт, вспышка, голограмма, контур, сортировка, силуэт, осколки). Признак нарушения — обращение к `SpriteRenderer` в презентации вне `Body/`. - **Материал вспышки обязан стоять на КАЖДОЙ части** (`_FlashAmount`): часть без него физически не умеет вспыхивать. Считать: 16 из 16 у костяного. - **Позиционное — по сокетам** (`FeetPoint`/`HeadPoint`/`ShotPoint`/`HitPoint`). Не разведён сокет — фолбэк на центр юнита, и искры бьют в живот вместо груди. Проверять на префабе, а не на глаз. - **Разлёт — по частям, сиблингом самой части**: осколки руки стартуют в пространстве руки, со счётчиком на один финальный колбэк, а не шестнадцать. ## Свечение оружия и цвета юнита — карта швов перед заходом (30.07) Следующий крупный заказ. Перед первой правкой знать вот это, чтобы не строить второй канал рядом с готовым: - **Материальное состояние тела подаётся ОДНИМ куском** (`BodyVisualState` → `IUnitBodyVisual.Apply`) раз в кадр, имена шейдерных параметров держит `BodyShaderIds`. Новый визуальный признак — поле туда, а не отдельный писатель в `UnitView`. - **Оружие и щит — отдельные части скелета** со своими рендерерами и материалом вспышки. Светить клинок физически можно уже сейчас. - **НО шов адресует ТЕЛО ЦЕЛИКОМ:** `Apply` кладёт одно состояние на все части. Это первое, что придётся расширять, и делать это надстройкой поверх общего состояния (роль части: `Weapon`/`Shield`/`Body`), а не вторым независимым каналом: меч обязан вспыхивать вместе со всеми при ударе И светиться сам. Выносить оружие из тела в отдельный держатель — хуже: потеряются внутренняя сортировка группы и общий шаттер. - **Линия дуги для трейла уже считается офлайн:** `RigSweep` отдаёт путь предмета с разбивкой на windup / strike / recovery и площадь по спрайту. Слеш-трейл живёт на strike-фазе, её границы известны. - **Цвет берётся с юнита, не из префаба:** `UnitData.VfxColor` (там, где цвет ровно один) и `VfxPalette` (диапазон разброса частиц), плюс `ResolveVfxPalette()`. Хвост трейла — тот же свет, теряющий прозрачность, а НЕ переход во второй цвет. - **Bloom только на VFX, порог ≥ 1.0.** Свечение арта — отдельный заход; цвет ровно в 1.0 порог не пробивает. ## Дуга за клинком — где искать, если она «идёт не так» (07.08.2026) Самый дорогой эффект по числу заходов: чинился четырежды, и три раза корень лежал НЕ в нём. Порядок проверки — от эффекта вниз, потому что дуга — последний потребитель длинной цепочки. | Симптом | Где смотреть на самом деле | |---|---| | след лежит мимо клинка | геометрия предмета: `UnitHeldItem` — длина объявлена, направление берётся с меша рабочей части. Мерить угол «хват → остриё» против угла нарисованного клинка | | след не следует за мечом по ходу взмаха | клип крутит узел `Weapon_*` отдельно от кисти — запрещено, держит `WeaponFollowsTheHandTests` | | след исчезает мгновенно | `SwingArcTrailSeconds` (длина хвоста ВО ВРЕМЕНИ) и `SwingArcFadeOut`. В стенде — ещё и фиктивное время: делегат фазы зовётся на каждой перерисовке, нулевой шаг не должен двигать часы | | след «висит» дальше меча к концу удара | радиус сектора обязан СЛЕДОВАТЬ за рукой, а не помнить максимальный размах | Владельцы: `SwingArcGeometry` (плечо и остриё), `SwingArcLaunch` (все числа запуска), `SwingArcVfx.Tick` (шаг жизни). Все трое зовутся и боем, и стендом — считать что-либо из этого своими руками запрещено, держит `SwingArcSingleOwnerTests`. **Урок, который стоит помнить дольше самой дуги.** Симптом читался как дефект эффекта и трижды в нём же чинился. Все правки были нужны, но корень лежал двумя слоями ниже — в риге, — и нашёлся не рассуждением, а ЗАМЕРОМ: угол вектора «хват → остриё» против угла нарисованного клинка, два числа. Когда эффект «почти правильный», спрашивать надо не его, а то, из чего он считается. ## Граница со смежными скиллами (режем чётко) Фидбэк стоит на стыке трёх скиллов. На каждом стыке — взаимная ссылка «см. другой скилл», а не спор за файл. - **combat-sim** владеет **боевым временем**: `TimeScaleService` (единственный писатель `Time.timeScale`, композит `GameSpeed × Cinematic`, пауза, шов под геймплейный хрономант) и шов sim→MessagePipe. `CombatFeelDirector` (мой) — **потребитель**: дёргает `TimeScaleService.CinematicPulse`/`PlayCinematicSequence` и `IScreenShake.Shake`. Тип `CinematicSegment` живёт на шве в `TimeScaleService` (им владеет combat-sim), FeelDirector его конструирует. Инвариант «`timeScale` пишет только `TimeScaleService`» — за combat-sim. - **audio** владеет звуком: `IAudioService`, FMOD, стингеры, микс. Пересечение — `TimeScaleService` толкает slowmo-питч через `IAudioService.SetGlobalParameter` (`AudioParameters.TimeScale`): вызов геймплейный (combat-sim), параметр — audio. Джус и звук на одно событие подписываются НЕЗАВИСИМО (оба слушают MessagePipe/sim), не через друг друга. - **data-authoring** владеет **ОПРЕДЕЛЕНИЕМ** контента-SO. Целевой `VfxData` (id, ссылка на VFX-префаб, параметры, loc — если нужен) — как `EffectData`: определение за data-authoring. **Спавн-механика** (пул, точки-сокеты, презентер, привязка к событию) — моя. Ровно как эффект: определение — data-authoring, поведение/спавн — здесь. ## Шов префаб-VFX ПОСТРОЕН Зеркало `UnitData.ViewPrefab`, и он уже работает: 1. **`VfxData`** SO (`Data/Definitions/`, владеет `data-authoring`): `id` (`domain.name`), ссылка на префаб, sorting layer/order, `DefaultDirDeg`. 2. **`CombatVfx`** + `PooledVfx` (здесь): пул на префаб, `Get` → позиционировать в мировую точку-сокет → `Play`, авто-`Release` по завершению. **Ключ пула — `EntityId`, не `int`.** Относительный order детей приходит из самого префаба, а не из кода. 3. Презентер по боевому событию резолвит `VfxData` и просит проиграть в точке (`ShotPoint`/`HitPoint`/`FeetPoint` на `UnitView`); `dirDeg = null` → `VfxData.DefaultDirDeg`. `PixelBurst*` мигрирован и удалён. Кодом законно остаются `DeathShatter`/`ShatterMesh` (меш режется из спрайта конкретного юнита) и dev-слой `CombatStatusOverlay`. Детали и антипаттерны — `references/vfx-and-pooling.md`. ## Как я авторю фидбэк-код — ГИБРИД (файл + проверка через MCP) 1. **Пишу C#-файлы напрямую** (`Write`/`Edit`) — контролирую код и его слой (Presentation
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る