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,OnGameStateChangedOnNewGame→ScriptPlayer.Stop()+ResetNani()+VariablesManager.ResetAllVariables()OnLoadGame→ScriptPlayer.Stop()+ResetNani()GameStates.Off/Win/Fail→ScriptPlayer.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(конец диалога, пауза на выбор).
Алгоритм:
OnPrintStarted— закрытие предыдущей реплики (если без voice), эмитOnVoiceStart, старт/продолжение поллинга, немедленная реконсиляция черезPollVoice()(voice мог уже играть к моменту события:@printawaitитPlayVoiceдо фаер'инга).- Поллинг через
TimeController.AddCallbackловит любые transitions path и эмититOnVoiceStop/ запоминает нового автора как cached. OnPrintFinished—OnVoiceStop, если у завершившейся реплики не было собственной voice. Если voice играет — закрытие через поллинг (voice имеет право продолжаться после печати текста).OnNaniStop/App.OnExit—FlushAll, закрытие всех открытых реплик.
Жизненный цикл: подписки в 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:
Play→timeScale = 1, возобновление звуковPaused→timeScale = 0, остановка всех звуковOff→Close()
Модели
| Класс | Описание |
|---|---|
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 (для тестирования сцен галереи в чистом состоянии). |