Аудио-система (шаги / приземление / прыжок / эмбиент)
Песочница: Assets/_Sandbox/Audio/AudioSandbox.unity. Всё аудио идёт через Master Audio (DarkTonic);
проигрывание — по имени Sound Group через статический API, поэтому рантайм-спавн игрока (PurrNet)
ничего в сцене подвязывать не обязан.
Принцип
- Источник событий шага/земли — iStep
FootIK, прыжка —JumpController, скорость —MinimalLocomotion. Все три висят на под-объекте персонажаSM_Chr_..._Splited(скинд-меш + Animator) — этот же объект есть у сетевых реплик, поэтому звук у владельца и реплик одинаков. По сети звук НЕ гоним: каждый клиент сам озвучивает всех видимых персонажей, а «чужие тише» получается само за счёт 3D-затухания Master Audio.
Компоненты (все в _Sandbox/Audio/, кроме локо/прыжка в _Sandbox/PlayerAnimator/)
FootstepAudio(наSM_Chr_..._Splited) — сердце системы:- Шаги:
FootIK.onFootstepLeftStart/RightStart→ по тегу земли (IKResult.primaryHitTransform) выбирает Sound Group. - Громкость шагов масштабируется от
MinimalLocomotion.CurrentSpeed(ремапspeedForMin/Max→min/maxVolume, со сглаживаниемspeedSmoothTime). Питч отдан группе MA (её random pitch). Speed-питч убран по решению. - Direction Duck: при резкой смене направления (реверс/стрейф) шаги приглушаются на окно (
duckVolumeScale, восстановлениеduckRecovery) — гасит лишние «переступ»-шаги от бленда анимации, не ломая ритм прямого бега. Направление берётся изMinimalLocomotion.LocalVelocity(сглаженоdirSmoothTime; на репликах шумит). - Приземление:
FootIK.onGroundedEnteredпосле реального отрыва → 1–2 шага (Land Step Count) с опц. задержкой; surface-aware, либо отдельнаяLand Sound Group. - Прыжок: событие
JumpController.Jumped(момент отрыва) → общий FX черезJump Sound Group(пока пустой = молчит). - Поля групп — дропдауны
[SoundGroup](MA), теги — дропдаун[TagSelector](наш,TagSelectorAttribute+ драйвер вEditor/). JumpController— добавлено публичное событиеJumped(бросается на реальном отрыве, не на сходе с уступа).MinimalLocomotion— добавленоCurrentSpeed(горизонтальная скорость из дельты трансформа; живёт и на репликах).AmbientSoundActivator— чинит MAAmbientSoundв сетевой игре: ждёт появления AudioListener (камера игрока спавнится позже) и переактивирует эмбиент, иначе он «сдаётся» на старте без слушателя.Editor/FootstepAudioEditor.cs— инспектор с live-строкой (Current Speed / Footstep Volume в Play mode) + драйвер тегов.
Настройка Master Audio (в сцене, объект MasterAudio)
- Sound Groups по поверхностям:
Footstep_Concrete/Earthground/Grass/Gravel/IceSnow/Metal/Mud/Water(Robotic удалён). Режим создания групп — One Group With Variations; вариации — Randomized; 3D-дальность — через Audio Source Template = «Max Distance 20». - Эмбиент-группы:
Ambient_WaterStream,Ambient_Wind— Looped + 3D (min/max ≈ 3/25). - Прыжок: создать группу и указать её в
FootstepAudio → Jump Sound Group(сейчас пусто). - Определение поверхности — теги
Surface_<Material>на коллайдерах земли (слой Default=0; маска FootIK ловит слои 0 и 15).
Что есть в сцене
MasterAudio(+ демо-группыCue-*/Phrase-*— чужие, к шагам не относятся),PlaylistController.SurfaceTests— плитки-поверхности (Cube + BoxCollider + тег) в ряд для проходки; они же префабами вSurfaces/.SpatialTest_WaterStream/SpatialTest_Wind— MAAmbientSound+AmbientSoundActivator(тест 3D-эмбиента).CharacterAudioTest.prefab— игрок, спавнится в рантайме.
Важные нюансы
- Громкость в MA (
volumePercentage) зажата 0..1 — «громче единицы» из компонента не сделать. Хочешь лэнд/прыжок громче → отдельная группа с бОльшей громкостью или шина → Unity-микшер с +dB (см. TODO). - Имена групп должны совпадать (дропдауны это гарантируют, если группа существует).
- Аудио — сменный слой: новый пак = переуказать клипы в группах MA, код не трогается.
TODO
- Шины + Unity Audio Mixer (следующая сессия):
- В инспекторе
MasterAudioвверху — секция Bus. Завести шины:Footsteps / Jump / Ambient / Interactables / UI. - Каждой Sound Group выставить её Bus (дропдаун Bus у группы):
Footstep_*→ Footsteps,Ambient_*→ Ambient, Jump → Jump. - Создать Unity
AudioMixerс группами тех же категорий; у каждой шины поле Unity Mixer Group (GroupBus.mixerChannel) связать с ней. - Бустить лэнд/прыжок теперь можно gain'ом на их шине/mixer-группе (там +dB допустим). API при нужде:
MasterAudio.RouteBusToUnityMixerGroup/RouteGroupToUnityMixerGroup.
- В инспекторе
- Звуки интерактиблов (дверь, ключ, обменник, монетка, сундук) — через MA-группы +
EventSoundsили маленький триггер-компонент. - Интеграция купленного пака (raw ваншоты по поверхностям) — завести группы, переуказать клипы.
- (опц.) звук старта прыжка, pitch-jitter, раздельные группы walk/run,
DynamicSoundGroupCreatorдля модульности, когда групп станет 50+. - Шаги от поворота камеры: доигрывать шаг при повороте на угол (переступ на месте), с рейт-лимитом «не чаще чем раз в X сек». Пока только мысль.
- Direction Duck — ложный триггер после полной остановки:
_smoothedDirдержится через стоп, поэтому «шёл назад → стоял пару сек → пошёл вперёд» ошибочно даёт duck. Фикс: инвалидировать направление (_dirValid = false) после простоя (скорость ниже порога дольше X сек), чтобы возобновление движения задавало свежее направление без duck'а.
Как сделать лэнд/прыжок громче (без дублирования групп)
- В MA один голос не превышает громкость 1.0 (
volumePercentage0..1). - Наложение:
Land Step Count = 2,Land Step Spacing = 0→ два случайных варианта складываются = полнее/громче. - Относительно: держать обычные шаги ниже 1 (
Max Volume ~0.7), лэнд на 1.0 — выделяется. - Настоящий +dB буст (громче максимума) — только через шину → Unity-микшер (см. TODO). Отдельная Land-группа оправдана лишь если нужен ДРУГОЙ звук, а не просто громче.
Заметки по среде (для агента)
- Sound Groups и шины MA создаются/правятся в инспекторе
MasterAudio(drag клипов на зону создания), НЕ через MCP. MCP умеет: свойства компонентов, GameObjects/префабы, теги/слои, refresh/консоль. - Режим создания групп у MA стоит
One Group With Variations; Audio Source Template =Max Distance 20(3D-дальность шагов). - MCP-инструмент
execute_codeв этой среде падает (ошибка mono) — не полагаться на него. - Проверка компиляции:
refresh_unity+read_console(errors). Долгий domain reload иногда даёт "timeout" у refresh, но компиляция при этом проходит — сверяйся по консоли, а не по таймауту.