NaniExtensions

Мост между фреймворком Vortex и визуальной новеллой Naninovel. Содержит подпакеты разных слоёв.

Назначение

  • Трансляция настроек громкости Vortex в Naninovel
  • Управление Nani-сценами из Vortex (пауза, стоп, сброс акторов)
  • Многоканальная локализация (общий язык, диалоги, озвучка)
  • Управление катсценами на Spine-анимациях через Nani-бэкграунды

Вне ответственности: Naninovel-скрипты, контент сцен, настройка Spine-ассетов.

Подпакеты

Подпакет Сборка Слой Назначение
Core ru.vortex.nani.core 3 NaniWrapper — ленивый доступ к сервисам Naninovel
AudioSystem ru.vortex.nani.audiosystem 3 Трансляция громкости, управление Nani-аудио, NaniVoicePlayBus
CutsceneSystem ru.vortex.nani.cutscenes 3 Контроллер Spine-катсцен
LocalizationSystem ru.vortex.nani.localization 2 Драйвер локализации с каналами
QuestSystem ru.vortex.nani.quests 3 Условие квеста NaniPlayerState — реакция на старт/стоп Nani-плеера (defineConstraints: USING_VORTEX_QUESTS, USING_NANINOVELL)
SaveSystem ru.vortex.nani.saves 3 NaniDataSaveController — сохранение/восстановление Nani-переменных через GameController
Misc ru.vortex.nani.misc 3 Точечные хэндлеры сцены (активный говорящий, баббл, эмоции, ZPosition, тестовые тулзы галереи)

Активация всего семейства Nani-пакетов — через символ USING_NANINOVELL, который выставляется тогглом naninovellExt (SdkSettings, атрибут [DefineSymbol("USING_NANINOVELL")]).


Core

Namespace: Vortex.NaniExtensions.Core

NaniWrapper — статический класс с lazy-кешированным доступом к сервисам Naninovel через Engine.GetService<T>().

Доступные сервисы

AudioManager, StateManager, L10N, CommunityL10N, ScriptPlayer, BackgroundManager, CharacterManager, TextPrinterManager, ChoiceHandlerManager, UnlockableManager, UIManager, VariablesManager

Жизненный цикл

  • [RuntimeInitializeOnLoadMethod] — подписка на GameController.OnNewGame, OnLoadGame, OnGameStateChanged
  • OnNewGameScriptPlayer.Stop() + ResetNani() + VariablesManager.ResetAllVariables()
  • OnLoadGameScriptPlayer.Stop() + ResetNani()
  • GameStates.Off/Win/FailScriptPlayer.Stop() + ResetNani()

API

Метод Описание
ResetNani() Остановка всего аудио, сброс переменных, скрытие бэкграундов, персонажей, текстовых принтеров, сброс выборов
NaniIsPlaying() true если ScriptPlayer играет или видим хэндлер выбора

NaniSessionService

Адаптер Naninovel.Engine под контракт IGameSessionService из Sdk/Core. Регистрируется автоматически через [RuntimeInitializeOnLoadMethod]. После регистрации GameController дожидается Engine.Initialized перед каждым переходом в Play (после NewGame и OnLoad). До этого ожидание было жёстко зашито в Sdk/Core — теперь Sdk/Core не знает о Naninovel, и зависимость живёт исключительно здесь.

public sealed class NaniSessionService : IGameSessionService
{
    public bool IsReady => Engine.Initialized;
    public string Name => "Naninovel.Engine";
}

LogicChainsExt — NaninovelInitialized

Условие для логических цепочек (LogicChainsSystem), лежит в Core/LogicChainsExt/. Наследник UnityCondition, ждёт Engine.Initialized (через Engine.OnInitializationFinished).

Симметрично условию SystemsLoaded из ru.vortex.unity.logicconditions (которое ждёт App.Running): поставленные на один коннектор вместе они дают конъюнкцию — переход цепочки происходит только когда готовы обе подсистемы, и Vortex, и Naninovel, независимо от того, кто финишировал первым. Типовое применение — этап «Waiting Loading» цепочки-загрузчика приложения (детальный пример — в README LogicChainsSystem (Unity)).

Появляется в дропдаунах условий цепочки автоматически, пока подключён ru.vortex.nani.core.


AudioSystem

Namespace: Vortex.NaniExtensions.AudioSystem, Audio

NaniVortexAudioConnector

Трансляция настроек громкости каналов Vortex → Naninovel.

  • Каналы (bgm, sfx, voice, voiceCutscene) загружаются из AudioChannelsConfig через partial-расширение AudioChannelsConfigExtNani
  • При GameStates.Off — изменение настроек сразу проецируется в Nani
  • При запущенной игре — только через явные вызовы GetNaniBgmVolume(), GetNaniSfxVolume(), GetNaniVoiceVolume()
  • SetCutsceneMode(bool) — переключает источник громкости голоса между voiceChannel и voiceCutsceneChannel

AudioNaniController

Управление Nani-аудио из Vortex.

Метод Описание
StopNaniMusic() Пауза текущего BGM, сохранение пути в PausedMusicPath
PlayNaniMusic() Возобновление BGM из PausedMusicPath
StopNaniVoice() Остановка голоса
StopNaniSfx() Остановка всех SFX

AudioChannelsConfigExtNani

Partial-расширение AudioChannelsConfig (сборка ru.vortex.unity.audiosystem.ext). Добавляет 4 поля с атрибутом [AudioChannelName] для маппинга Nani-каналов на Vortex-каналы.

NaniVoicePlayBus

Шина событий начала/завершения реплики персонажа. Объединяет два источника — ITextPrinterManager и IAudioManager — в единый контракт:

public static event Action<string> OnVoiceStart;   // authorId говорящего
public static event Action<string> OnVoiceStop;    // authorId говорящего

Воспроизведение voice детектируется поллингом IAudioManager.GetPlayedVoice(). Шина корректно ловит:

  • конец voice (path → null);
  • смену voice на другого актора (pathA → pathB) даже без null-окна между ними;
  • «тихий переход» (тот же автор продолжает с новой voice-дорожкой — аниматор остаётся в Forward, ни Stop, ни Start не эмитятся);
  • реплику без voice — Stop эмитится в PrintFinished, чтобы подписчик не залипал в состоянии «говорит» при отсутствии следующей PrintStarted (конец диалога, пауза на выбор).

Алгоритм:

  1. OnPrintStarted — закрытие предыдущей реплики (если без voice), эмит OnVoiceStart, старт/продолжение поллинга, немедленная реконсиляция через PollVoice() (voice мог уже играть к моменту события: @print awaitит PlayVoice до фаер'инга).
  2. Поллинг через TimeController.AddCallback ловит любые transitions path и эмитит OnVoiceStop / запоминает нового автора как cached.
  3. OnPrintFinishedOnVoiceStop, если у завершившейся реплики не было собственной voice. Если voice играет — закрытие через поллинг (voice имеет право продолжаться после печати текста).
  4. OnNaniStop / App.OnExitFlushAll, закрытие всех открытых реплик.

Жизненный цикл: подписки в App.OnStart, отписка в App.OnExit. Не требует регистрации/инициализации со стороны проекта.


CutsceneSystem

Namespace: Vortex.NaniExtensions.CutsceneSystem, Vortex.NaniExtensions.CutsceneSystem.Models

Контроллер Spine-анимированных катсцен, отображаемых как Naninovel SpineBackground.

CutsceneController

Статический контроллер. Жизненный цикл:

Open(key) → загрузка CutsceneData → SpineBackground → LoadPhase → [NextPhase]* → Close
Метод Описание
Open(key, canBeClosedByButton) Загрузка катсцены по Addressable-ключу, запуск первой фазы
NextPhase() Переход к следующей фазе
Close() Остановка, очистка, удаление бэкграунда

Фазы:

  • Каждая CutscenePhase — анимация (looped/не looped) + опциональный ambient-звук
  • Не looped-анимации автоматически переходят к следующей фазе
  • Spine-события (Event) маппятся на звуки через EventToAudioData

Реакция на GameStates:

  • PlaytimeScale = 1, возобновление звуков
  • PausedtimeScale = 0, остановка всех звуков
  • OffClose()

Модели

Класс Описание
CutsceneData ScriptableObject: SkeletonDataAsset, List<CutscenePhase>, List<EventToAudioData>, List<string> SexSceneAmbients
CutscenePhase Фаза: AnimationKey, AnimationLooped, AmbientAudioPack
CutscenePhaseData Диалоговые данные: AuthorTextKey, DialogueTextKey, озвучка (Ru/En)
EventToAudioData Маппинг Spine-события → звук: EventName, AudioPack

CutsceneData.SyncWithSpine() — Editor-кнопка: синхронизирует фазы и события с SkeletonDataAsset.


Misc

Namespace: Vortex.NaniExtensions.Misc Сборка: ru.vortex.nani.misc

Точечные хэндлеры для интеграции Nani-сцены с проектным UI и логикой. Каждый — самостоятельный MonoBehaviour, вешается на UI-объекты сцены и работает поверх NaniWrapper/NaniVoicePlayBus.

Хэндлер Что делает
ActiveCharacterHandler Отслеживает «кто говорит» через NaniVoicePlayBus.OnVoiceStart/Stop и переключает визуал активного актора (StateSwitcher / выделение).
CharacterVoiceTweenerHandler Связывает NaniVoicePlayBus с TweenerHub на персонаже: Forward на старте voice, Back на завершении.
LookCharacterHandler Поворот персонажа на текущего говорящего (источник — NaniVoicePlayBus).
VisibilityCharacterHandler Скрытие/показ персонажей по правилам сцены (на основе CharacterManager.GetActor/Appearance).
DialogBubbleSwitcher Переключатель состояний диалогового баббла (типы реплик, эмоции, фон).
BubblePositionTarget Якорь позиции баббла относительно мирового объекта (актор/слот).
TextBubbleResizer Динамический размер баббла под длину текста реплики (после OnPrintStarted).
ZPositionSwitch Переключение Z-позиции по доменному стейту (Active/Inactive говорящий).
ResetAllGalleryCardsHandler Editor-инструмент: сбрасывает прогресс открытых карт галереи в UnlockableManager (для тестирования сцен галереи в чистом состоянии).