Документ для тех, кто подключает ядро к своей игре или расширяет репозиторий. Нормативные контракты и дорожная карта — в DGF_SPEC.md; здесь — практическая карта кода и типичные задачи.
С нуля за 10 минут: QUICK_START.md → сцена RogueliteArena, LLM, F9. Оглавление всех Docs: DOCS_INDEX.md.
| Шаг | Документ / место | Зачем |
|---|---|---|
| 0 | QUICK_START.md, ../../_exampleGame/Docs/UNITY_SETUP.md | Быстрый старт и пошаговая настройка Example Game в Unity |
| 1 | DGF_SPEC.md §1–5, §8–9 (§9.4 — главный поток Unity после LLM) | Цели ядра, LLM/stub, Lua, потоки |
| 2 | AI_AGENT_ROLES.md | Роли агентов, placement, выбор модели |
| 3 | LLMUNITY_SETUP_AND_MODELS.md | LLMUnity, LM Studio / OpenAI HTTP, PlayMode-тесты, Lua-пайплайн |
| 4 | ../README.md (хост CoreAiUnity) |
Сборки, папки, DI, промпты, MessagePipe |
| 5 | GameTemplateGuides/INDEX.md | Короткие рецепты под тайтл |
| 6 | ../../_exampleGame/README.md | Пример игры и точки входа |
Принцип: CoreAI.Core — переносимый C# без реализации под конкретный движок; CoreAI.Source — слой Unity (DI, сцена, LLM-адаптеры). Нормативно зафиксировано в DGF_SPEC §3.0.
| Сборка | Папка | Ограничение |
|---|---|---|
| CoreAI.Core | Assets/CoreAI/Runtime/Core/ |
Без Unity (noEngineReferences). Контракты ИИ, оркестратор, очередь QueuedAiOrchestrator, снимок сессии, песочница MoonSharp, парсинг Lua, процессор конверта. |
| CoreAI.Source | Assets/CoreAiUnity/Runtime/Source/ |
Unity: VContainer, MessagePipe, маршрутизация LLM (RoutingLlmClient, LlmRoutingManifest), LLMUnity/OpenAI HTTP, логирование, роутер команд, биндинги Lua (report / add). Пакет com.nexoider.coreaiunity. |
| CoreAI.Tests | Assets/CoreAiUnity/Tests/EditMode/ |
EditMode NUnit, без Play Mode. |
| CoreAI.PlayModeTests | Assets/CoreAiUnity/Tests/PlayMode/ |
Play Mode (оркестратор, опционально LM Studio через env). |
| CoreAI.ExampleGame | Assets/_exampleGame/ |
Демо-арена; зависит от Source. |
Проверка: компиляция — dotnet build по сгенерированным *.csproj (Unity/Rider) или сборка из IDE; NUnit EditMode / Play Mode — в Unity Test Runner (Window → General → Test Runner). Источник истины для сценариев с UnityEngine и тестовыми ассетами — Test Runner, а не «голый» dotnet test без Unity.
Правило: игровая логика тайтла не должна «протекать» в Core без необходимости. Новые игровые API для Lua — через реализацию IGameLuaRuntimeBindings в Source (или в сборке игры), а не правки песочницы в обход whitelist.
Шаблон задуман так, чтобы по умолчанию работал “разумно”, но при необходимости позволял точечную настройку без переписывания ядра.
- DI + MessagePipe + лог:
CoreAILifetimeScopeрегистрируетIGameLogger, брокерApplyAiGameCommand,IAiGameCommandSink. - Оркестрация:
IAiOrchestrationServiceпо умолчанию —QueuedAiOrchestratorвокругAiOrchestrator. - Lua‑конвейер:
AiGameCommandRouterпереносит обработку на main thread и запускаетLuaAiEnvelopeProcessor. - Лимиты Lua:
LuaExecutionGuardограничивает wall‑clock и “шаги” (best‑effort). - Prompts: цепочка system/user по манифесту → Resources → встроенный fallback.
- Версии Programmer (Lua + data overlays): в Unity‑слое по умолчанию сохраняются на диск (File* store).
- World Commands: Lua API
coreai_world_*публикует команды мира в шину, выполнение — на main thread (см. WORLD_COMMANDS.md).
- LLM backend:
OpenAiHttpLlmSettings(OpenAI‑compatible HTTP) иLlmRoutingManifest(маршрутизация по ролям). - Промпты:
AgentPromptsManifest(переопределения system/user и кастомные роли). - Логи:
GameLogSettingsAsset(фильтр по фичам и уровню). - World Commands:
World Prefab Registry(whitelist префабов для спавна).
Рекомендация для тайтла: держать настройки в 1‑2 ScriptableObject‑ассетах и версионировать их в git (без секретов).
- В ядре CoreAI используйте
IGameLoggerиGameLogFeature— это встроенные «теги» подсистем и фильтр по уровню черезGameLogSettingsAsset(аналог структурированных категорий без отдельного NuGet). Вывод в консоль Unity идёт черезFilteringGameLogger→UnityGameLogSink; не разбрасывайтеDebug.Logпо бизнес-коду. - Serilog / NLog / Microsoft.Extensions.Logging в Unity подключают отдельно, если нужен вывод в файлы, Seq, Elasticsearch и т.д. Для кода ядра они не требуются: достаточно реализовать свой
IGameLoggerили заменить sink, чтобы дублировать записи в Serilog, не смешивая два стиля логирования в одном слое. - Фильтрация в консоли Unity: по префиксу сообщения (категория из
GameLogFeature), поTraceIdв цепочке оркестратора/команд (см. README хоста), плюс настройки минимального уровня в ассете логов. - Editor (меню, setup без DI):
CoreAIEditorLog— единая точка сообщений редактора.
Упрощённая схема рантайма:
flowchart LR
Game["Игра: IAiOrchestrationService.RunTaskAsync"]
Orch["AiOrchestrator"]
LLM["ILlmClient"]
Sink["IAiGameCommandSink → MessagePipe"]
Router["AiGameCommandRouter"]
LuaP["LuaAiEnvelopeProcessor"]
Lua["SecureLuaEnvironment + MoonSharp"]
Game --> Orch
Orch --> LLM
Orch --> Sink
Sink --> Router
Router --> LuaP
LuaP --> Lua
LuaP -->|"ошибка + Programmer"| Orch
- Игра вызывает
IAiOrchestrationService.RunTaskAsync(AiTaskRequest)(роль, hint,Priority,CancellationScope, опционально поля ремонта Lua иTraceId). - Реализация по умолчанию —
QueuedAiOrchestrator(лимит параллелизма, приоритет, отмена предыдущей задачи с тем жеCancellationScope) вокругAiOrchestrator.AiOrchestratorназначаетTraceId, собирает промпты, вызываетILlmClient.CompleteAsync; приIRoleStructuredResponsePolicyдля роли возможен один повтор с подсказкойstructured_retry:в user/hint. Затем публикуетсяApplyAiGameCommand(AiEnvelope,TraceId, …). Метрики —IAiOrchestrationMetrics(лог приGameLogFeature.Metrics). - В DI
ILlmClient—LoggingLlmClientDecoratorвокругRoutingLlmClient(или legacy один клиент): внутри —OpenAiChatLlmClient/MeaiLlmUnityClient/StubLlmClientпоLlmRoutingManifestи роли. ЛогGameLogFeature.Llm(LLM ▶/LLM ◀/LLM ⏱), строка бэкендаRoutingLlmClient→OpenAiHttpи т.п. Для «это stub?» —LoggingLlmClientDecorator.Unwrap(client). - Подписчик
AiGameCommandRouterполучаетApplyAiGameCommandиз MessagePipe и переносит обработку на главный поток Unity (UniTask.SwitchToMainThread), затем вызываетLuaAiEnvelopeProcessor.Process: из текста извлекается Lua код, выполняется в песочнице с API изIGameLuaRuntimeBindings; в лог[MessagePipe]попадаетtraceIdтой же задачи. - При успехе / ошибке публикуются
LuaExecutionSucceeded/LuaExecutionFailed(TraceIdсохраняется). Для роли Programmer при ошибке оркестратор вызывается повторно с контекстом ремонта и тем жеTraceId(до 3 попыток по умолчанию, настраивается черезCoreAISettings.MaxLuaRepairRetries).
Важно: геймплейные системы могут подписываться на ApplyAiGameCommand и реагировать на типы команд; не парсить сырой текст LLM вне общего конвейера, если хотите единообразия. Подробнее логи и таймаут: LLMUNITY_SETUP_AND_MODELS.md §1 (блок про CoreAI) и таймаут.
Unity — главный поток (кратко): после QueuedAiOrchestrator продолжение async часто выполняется не на main thread; Publish из оркестратора может прийти с пула. Любой код с UnityEngine, FindObjectsByType, сценой и UI — только на главном потоке или после явного маршалинга. Шаблон делает маршалинг в AiGameCommandRouter; свои подписчики на MessagePipe должны повторять тот же принцип. Нормативно и с чеклистом: DGF_SPEC.md §9.4.
| Режим | Где настраивается | Когда выбирается |
|---|---|---|
LLMUnity (LLMAgent на сцене) |
Инспектор LLM / LLMAgent | По умолчанию, если HTTP выключен: фактический клиент — MeaiLlmUnityClient, в контейнере обёрнут в LoggingLlmClientDecorator. См. LLMUNITY_SETUP_AND_MODELS.md. |
| OpenAI-compatible HTTP | Asset CoreAI → LLM → OpenAI-compatible HTTP, поле на CoreAILifetimeScope |
OpenAiHttpLlmSettings.UseOpenAiCompatibleHttp — тогда внутри декоратора реализация — OpenAiChatLlmClient. |
Символ COREAI_NO_LLM: в контейнере остаётся цепочка с StubLlmClient / HTTP при необходимости — детали в DGF_SPEC §5.2.
Наблюдаемость: GameLogFeature.Llm (запросы LLM); GameLogFeature.Metrics (метрики оркестратора, не входит в AllBuiltIn — включите вручную в ассете). Старые Game Log Settings без бита Llm дополняются при OnValidate. Фильтр по traceId связывает LLM ▶/◀ и ApplyAiGameCommand.
-
Цепочка системного промпта: манифест (опционально) →
Resources/AgentPrompts/System/<RoleId>.txt→ встроенный fallback (BuiltInAgentSystemPromptTexts). -
Встроенные роли: см.
BuiltInAgentRoleIdsи тестыAgentRolesAndPromptsTests. -
Кастомные агенты: используйте
AgentBuilderдля создания новых агентов с уникальными инструментами. См. AGENT_BUILDER.md. -
User payload: по умолчанию — JSON вида
{"telemetry":{...},"hint":"..."}изGameSessionSnapshot.Telemetry; при ремонте Lua добавляются поляlua_repair_generation,lua_error,fix_this_lua(AiPromptComposer). -
Память агента (опционально): агент сохраняет память через MEAI tool calling:
{"name": "memory", "arguments": {"action": "write", "content": "..."}}— перезаписать{"name": "memory", "arguments": {"action": "append", "content": "..."}}— дописать{"name": "memory", "arguments": {"action": "clear"}}— очистить
По умолчанию память выключена у всех ролей, кроме Creator (см.
AgentMemoryPolicy). В рантайме Unity память хранится вApplication.persistentDataPath/CoreAI/AgentMemory/<RoleId>.json.
- Парсинг:
AiLuaPayloadParser(markdown → JSONExecuteLua). - Исполнение:
SecureLuaEnvironment,LuaExecutionGuard,LuaApiRegistry. - Лимиты:
LuaExecutionGuardвключает best-effort ограничение wall-clock и шагов (см.InstructionLimitDebugger), чтобы бесконечные циклы Lua не могли зависнуть навсегда. - Дефолтные игровые вызовы в шаблоне:
LoggingLuaRuntimeBindings—report(string),add(a,b). - Расширение: зарегистрируйте свою реализацию
IGameLuaRuntimeBindingsвCoreAILifetimeScope(вместо или поверх дефолтной — по политике проекта; избегайте дублирования интерфейса в контейнере без явной замены). - Управление миром (рантайм): встроенная фича World Commands добавляет Lua‑API
coreai_world_*и выполняет команды на главном потоке Unity через MessagePipe. См. WORLD_COMMANDS.md.
Это отдельное файловое хранение CoreAI под Application.persistentDataPath (через File.WriteAllText / чтение при создании store), не Neo SaveProvider и не общий игровой сейв тайтла.
| Что | Путь по умолчанию |
|---|---|
| Версии Lua Programmer | persistentDataPath/CoreAI/LuaScriptVersions/lua_script_versions.json |
| Data overlays | persistentDataPath/CoreAI/DataOverlayVersions/data_overlays.json |
- После перезапуска игры при старте контейнера store снова читает JSON: восстанавливаются текущий текст (
current) и история ревизий; оркестратор/Lua используют уже загруженное состояние. - Android / iOS / Desktop — обычная запись в каталог приложения; данные сохраняются между сеансами, пока пользователь не удалит приложение или не очистит «данные приложения».
- WebGL —
persistentDataPathв Unity мапится на хранилище браузера (IndexedDB и т.п.): между сессиями обычно работает, но пользователь может очистить данные сайта; возможны ограничения квоты — уточняйте по документации Unity для вашей версии под WebGL. - Для синхронизации с облаком / одним сейвом игры нужна отдельная интеграция (копирование файлов, свой провайдер или зеркалирование после
RecordSuccessfulExecution).
| Сборка | Запуск | Что проверяет |
|---|---|---|
| CoreAI.Tests | Test Runner → EditMode | Промпты, stub LLM, песочница Lua, парсер конверта, LuaAiEnvelopeProcessor, композер repair, LuaProgrammerPipelineEndToEndEditModeTests (оркестратор → конверт → Lua → ошибка → повтор Programmer → успех). |
| CoreAI.PlayModeTests | Test Runner → PlayMode | Оркестратор по всем ролям; опционально реальный HTTP (переменные COREAI_OPENAI_TEST_* — см. LLMUNITY doc). |
Рекомендация: перед PR прогонять EditMode; PlayMode — при изменениях DI/сцены или HTTP-клиента.
- Сцена
RogueliteArena(см. Build Settings):CompositionRootсCoreAILifetimeScope,ExampleRogueliteEntry(арена + хоткеи). - F9 — задача Programmer (демо Lua +
report), компонентCoreAiLuaHotkey. - Дочерний
LifetimeScopeпримера:RogueliteArenaLifetimeScope— заготовка под фичи игры с Parent = ядро.
Подробности: ../../_exampleGame/README.md.
| Задача | Куда смотреть / что делать |
|---|---|
| Новая роль агента | Константа или строковый id; промпт в Resources или манифесте; при необходимости тест в AgentRolesAndPromptsTests. |
| Новый тип команды ИИ | Расширить обработку ApplyAiGameCommand.CommandTypeId (новый подписчик или ветка в игре); не смешивать с сырым текстом LLM без парсера. |
| Новые функции для Lua от LLM | Реализовать IGameLuaRuntimeBindings; регистрация делегатов в LuaApiRegistry (whitelist). |
| Управление миром из Lua | Использовать World Commands (coreai_world_*), настроить CoreAiPrefabRegistryAsset и назначить в CoreAILifetimeScope. См. WORLD_COMMANDS.md. |
| Смена модели / облако | LLMUNITY_SETUP_AND_MODELS.md; для продакшена не коммить API-ключи. |
| Мультиплеер | DGF_SPEC, AI_AGENT_ROLES (placement); авторитет LLM на хосте — ответственность игры. |
Ниже — практические “узкие места” при интеграции и способы сделать CoreAI более автоматичным, но настраиваемым.
Проблема: легко забыть настроить CoreAILifetimeScope (LLM backend, промпты, лог‑настройки, реестр префабов мира).
Упростить:
- Добавить Editor‑меню “CoreAI → Setup → Create Default Assets”:
GameLogSettingsAsset(с включеннымLlmи нужными фичами)OpenAiHttpLlmSettings(пустой шаблон)AgentPromptsManifest(опционально)CoreAiPrefabRegistryAsset(пустой whitelist)
- Добавить “CoreAI → Setup → Validate Scene” (проверка: есть
CoreAILifetimeScope, корректные ссылки, предупреждения).
Проблема: «почему молчит модель?» — потому что LLMAgent не найден или HTTP не включен, а ядро ушло в stub.
Упростить:
- В логах старта писать явное резюме: backend=stub/llmunity/http, почему выбран.
- В UI/дашборде показывать текущий backend и
traceIdпоследних запросов.
Проблема: команды могут приходить с пула потоков.
Упростить:
- Канонизировать одну точку “apply to Unity” (как сейчас
AiGameCommandRouter) и запрещать прямую обработку изISubscriber<T>без маршалинга. - Добавить небольшой util/шаблон
MainThreadCommandQueueдля проектов без UniTask.
Проблема: бесконечные циклы, расширение API, ошибки в Lua.
Упростить:
- Держать Lua API в виде малых фич (Versioning, World Commands, game‑bindings) и документировать каждую.
- По умолчанию включать лимиты (
LuaExecutionGuard) и логировать превышение лимитов как отдельный сигнал.
Проблема: Programmer меняет и код, и данные; нужен быстрый rollback.
Упростить:
- Стабильные ключи (usecase id / overlay key) и единый UI “Versions” в дашборде (показ original/current/history + reset).
- “Reset All” для аварийного восстановления.
Проблема: PlayMode тесты могут зависеть от модели/сети.
Упростить:
- Для CI: дефолт
COREAI_NO_LLMили stub‑профиль, обязательный EditMode прогон. - Для “integration” ветки: отдельный ручной job с env для HTTP и ограничением времени.
- EditMode:
CoreAI.Testsбез ошибок (промпты, Lua, парсеры, процессор конверта). - PlayMode: при изменениях
CoreAILifetimeScope, сцен,OpenAiChatLlmClientили PlayMode-тестов — прогнатьCoreAI.PlayModeTests. - Секреты: не коммитить API-ключи,
.envс ключами, локальные пути к моделям с персональными данными; для CI использовать переменные окружения (см. LLMUNITY_SETUP_AND_MODELS.md). - Документация: если меняется контракт или поток (§3 DGF / DI), обновить DGF_SPEC и при необходимости этот гайд в том же PR.
Крупные изменения контрактов фиксируйте в DGF_SPEC (версия в шапке). DEVELOPER_GUIDE описывает текущую карту кода; при расхождении с кодом приоритет у репозитория — обновите гайд в том же PR.
Версия этого гайда: 1.3 (апрель 2026) — TraceId, декоратор LLM, таймаут запроса, логи Llm/MessagePipe, Unwrap(stub).