Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Unity_в_действии_Джозеф_Хокинг_Рус.pdf
Скачиваний:
82
Добавлен:
21.06.2022
Размер:
26.33 Mб
Скачать

10.4. Фоновая музыка      261

и выберите в меню подходящую функцию. На этот раз нам предоставят текстовое поле для ввода числа, так как метод OnPlayMusic() принимает в качестве параметра число. Введите 1 для Intro Music, 2 для Level Music и произвольное число для No Music (у меня это был ноль). Инструкция switch в методе OnMusic() воспроизводит клип intro или level в зависимости от числа или останавливает воспроизведение, если число не равно ни 1, ни 2.

Щелкая на кнопках в процессе игры, вы сможете включать музыку. Великолепно! Код загружает аудиоклипы из папки Resources. Производительность воспроизведения оптимизирована. Осталось доработать две вещи: сделать отдельные элементы управления громкостью и обеспечить плавный переход при переключении музыки.

10.4.2. Отдельная регулировка громкости

В игре уже есть элемент управления громкостью, который сейчас влияет в числе прочего и на фоновую музыку. Но в большинстве игр громкость звуковых эффектов и музыки контролируется по отдельности. Давайте посмотрим, как этого достичь.

Первым делом нужно сделать так, чтобы компоненты AudioSources музыки игнорировали настройки компонента AudioListener. Мы хотим, чтобы регулятор громкости и кнопка отключения звука, связанные с глобальным компонентом AudioListener, продолжали влиять на все звуковые эффекты, но не затрагивали бы фоновую музыку. Листинг 10.11 содержит код, заставляющий источник музыки игнорировать громкость, задаваемую компонентом AudioListener. Заодно этот код создает регулятор громкости и возможность выключения музыки. Добавьте его к диспетчеру аудио.

Листинг 10.11. Раздельное управление громкостью музыки в диспетчере управления звуком

...

private float _musicVolume; ¬ Непосредственный доступ к закрытой переменной невозможен, только через функцию задания свойства.

public float musicVolume { get {

return _musicVolume;

}

set {

_musicVolume = value;

if (music1Source != null) { ¬ Непосредственно регулируем громкость источника звука. music1Source.volume = _musicVolume;

}

}

}

...

public bool musicMute { get {

if (music1Source != null) { return music1Source.mute;

}

return false; ¬ Значение предлагается по умолчанию, если AudioSource отсутствует.

}

set {

262      Глава 10. Звуковые эффекты и музыка

if (music1Source != null) { music1Source.mute = value;

}

}

}

public void Startup(NetworkService service) { Debug.Log("Audio manager starting...");

_network = service;

music1Source.ignoreListenerVolume = true; music1Source.ignoreListenerPause = true;

soundVolume = 1f; musicVolume = 1f;

status = ManagerStatus.Started;

}

...

¬Выделенный курсивом код уже был в сценарии, тут он приведен для справки.

Эти свойства заставляют компонент AudioSource игнорировать громкость компонента AudioListener.

Ключевой в этом коде является возможность непосредственной регулировки громкости в компоненте AudioSource с одновременным игнорированием источником глобальных параметров громкости, заданных в компоненте AudioListener. Существуют свойства для управления громкостью и включения/выключения звука отдельного источника музыки.

Метод Startup() инициализирует источник музыки со свойствами ignoreListener­ Volume и ignoreListenerPause, имеющими значение true. Как следует из их названий, они заставляют источник звука игнорировать глобальные настройки громкости в компоненте AudioListener.

Вы можете щелкнуть на кнопке Play и удостовериться, что существующий элемент регулировки громкости на громкость музыки больше не влияет. Значит, нам нужен в UI еще один элемент управления, который будет отвечать за громкость музыки; отредактируйте сценарий SettingsPopup в соответствии со следующим листингом.

Листинг 10.12. Элементы управления громкостью в сценарии SettingPopup

...

 

public void OnMusicToggle() {

Снова воспроизводим элемент управления

Managers.Audio.musicMute = !Managers.Audio.musicMute; ¬ включением звука, но на этот раз используя

Managers.Audio.PlaySound(sound);

musicMute.

}

 

public void OnMusicValue(float volume) {

Снова воспроизводим элемент

Managers.Audio.musicVolume = volume; ¬ управления громкостью звука,

}

но на этот раз используя musicVolume.

...

Особых пояснений этот код не требует — по большей части он повторяет элементы управления громкостью звука. Бросается в глаза замена свойств объекта AudioManager

с soundMute/soundVolume на musicMute/musicVolume.

10.4. Фоновая музыка      263

В редакторе создайте кнопку и ползунок. Вот последовательность ваших действий:

1.Измените высоту всплывающего окна на 225 (чтобы появилось место для дополнительных элементов управления).

2.Создайте UI-кнопку.

3.Сделайте ее потомком по отношению к всплывающему окну.

4.Поместите кнопку в точку с координатами 0, –60.

5.Раскройте иерархию кнопки и выделите текстовую метку.

6.Измените ее текст на Toggle Music.

7.Создайте ползунок (командой того же самого меню UI).

8.Сделайте ползунок потомком всплывающего окна и поместите его в точку с координатами 0, –85.

Свяжите эти UI-элементы с кодом в сценарии SettingsPopup. Найдите список OnClick/OnValueChanged в настройках UI-элементов, щелкните на кнопке со знаком + (плюс) для добавления новой записи и перетащите всплывающее окно на ячейку для объекта, после чего выберите в меню функцию. В первом случае это будет вариант OnMusicToggle(), во втором — OnMusicValue(). Обе функции находятся в разделе Dynamic Float.

Теперь запустите код и убедитесь, что на звуковые эффекты и фоновую музыку влияют разные элементы управления. Но на самом деле, это еще не все. Остался последний штрих — плавное микширование музыкальных треков.

10.4.3. Переход между песнями

В качестве финального штриха давайте заставим диспетчер управления звуком постепенно увеличивать и уменьшать громкость звука при переходе от одной мелодии к другой. Сейчас в процессе переключения мелодия просто обрывается, и начинается новый трек, что несколько режет ухо. Мы можем сгладить этот переход, сделав так, чтобы громкость предыдущего трека быстро затухала, в то время как громкость нового увеличивалась от нуля. Это простой, но хорошо продуманный код, объединяющий изученные вами методы регулировки громкости с сопрограммой, постепенно меняющей громкость.

Листинг 10.13 содержит код сценария AudioManager. Смысл происходящего сводится к простой концепции: теперь, когда у нас есть два отдельных источника звука, мы пользуемся ими для воспроизведения отдельных музыкальных треков и пошагово увеличиваем громкость одного источника, одновременно пошагово уменьшая громкость другого (как обычно, выделенный курсивом код уже присутствует в сценарии и показан для справки).

Листинг 10.13. Плавный переход между треками в сценарии AudioManager

...

[SerializeField] private AudioSource private AudioSource _activeMusic; ¬ private AudioSource _inactiveMusic;

Второй компонент AudioSource music2Source; ¬ (первый тоже сохраняем).

Следим за тем, какой из источников активен, а какой нет.

264      Глава 10. Звуковые эффекты и музыка

public float crossFadeRate = 1.5f;

private bool _crossFading; ¬ Переключатель, позволяющий избежать ошибок в процессе перехода.

...

public float musicVolume {

...

set {

_musicVolume = value;

if (music1Source != null && !_crossFading) { music1Source.volume = _musicVolume;

music2Source.volume = _musicVolume; ¬ Регулировка громкости обоих источников музыки.

}

}

}

...

public bool musicMute {

...

set {

if (music1Source != null) { music1Source.mute = value; music2Source.mute = value;

}

}

}

public void Startup(NetworkService service) { Debug.Log("Audio manager starting...");

_network = service;

music1Source.ignoreListenerVolume = true; music2Source.ignoreListenerVolume = true; music1Source.ignoreListenerPause = true; music2Source.ignoreListenerPause = true;

soundVolume = 1f; musicVolume = 1f;

_activeMusic = music1Source; ¬ Инициализируем один из источников как активный.

_inactiveMusic = music2Source;

status = ManagerStatus.Started;

}

...

private void PlayMusic(AudioClip clip) { if (_crossFading) {return;}

StartCoroutine(CrossFadeMusic(clip)); ¬ При изменении музыкальной композиции вызываем сопрограмму.

}

private IEnumerator CrossFadeMusic(AudioClip clip) { _crossFading = true;

_inactiveMusic.clip = clip; _inactiveMusic.volume = 0; _inactiveMusic.Play();

float scaledRate = crossFadeRate * _musicVolume;

10.4. Фоновая музыка      265

while (_activeMusic.volume > 0) {

_activeMusic.volume -= scaledRate * Time.deltaTime; _inactiveMusic.volume += scaledRate * Time.deltaTime;

yield return null; ¬ Эта инструкция yield останавливает операции на один кадр.

}

AudioSource temp = _activeMusic; ¬ Временная переменная, используемая, когда мы меняем местами переменные _active и _inactive.

_activeMusic = _inactiveMusic; _activeMusic.volume = _musicVolume;

_inactiveMusic = temp; _inactiveMusic.Stop();

_crossFading = false;

}

public void StopMusic() { _activeMusic.Stop(); _inactiveMusic.Stop();

}

...

Первым дополнением стала переменная для второго источника музыки. Вам нужно сохранить первый объект AudioSource, но создать его копию (убедитесь, что настройки остались теми же — установите флажок Loop), а затем перетащить его на ячейку панели Inspector. При этом код задает переменные для активного и неактивного состояний источника звука, но это закрытые переменные, которые не появляются на панели Inspector. Именно они определяют, музыка из какого источника воспроизводится в конкретный момент времени.

Теперь в процессе воспроизведения музыки код вызывает сопрограмму. Она заставляет второй объект AudioSource начать воспроизведение нового музыкального трека, в то время как старый воспроизводится на втором источнике звука. После этого сопрограмма пошагово увеличивает громкость новой музыки, одновременно уменьшая громкость старой. После завершения перехода (то есть в момент, когда уровни громкости поменялись местами) сопрограмма меняет местами «активный» и «неактивный» источники.

Потрясающе! Мы добавили фоновую музыку в аудиосистему игры.

FMOD: ЗВУКОВОЙ ИНСТРУМЕНТ ДЛЯ ИГР

Аудиосистема в Unity приводится в действие популярной программной аудиобиблиотекой FMOD. Ее можно скачать с сайта www.fmod.org, но в Unity она уже встроена, хотя и без наиболее нетривиальных функциональных возможностей (о них вы можете узнать на сайте библиотеки).

Эти нетривиальные функциональные возможности предлагает подключаемый к Unity модуль FMOD Studio, но для выполнения упражнений этой главы предоставленного по умолчанию набора функциональных возможностей более чем достаточно. В этот набор входят самые необходимые для создания аудиосистемы в играх компоненты. Они удовлетворяют нуждам большинства разработчиков, дополнительный же модуль требуется только для добавления в игры сложных звуковых эффектов.