Звук в Unity. Фоновая музыка.

Tulenber 3 July, 2020 ⸱ Intermediate ⸱ 4 min ⸱ 2019.4.1f1 ⸱

В какой-то момент каждый разработчик игры задумывается… а почему так тихо?

Если ваша игра не построена вокруг звукового сопровождения, как, например, Osu!, Guitar Hero или Hotline Miami, то вы вполне можете оказаться в ситуации, когда ваши игра уже почти готова, и тут вы понимаете: “Что-то не так”. Через пару минут размышлений оказывается что в игре нет звука =) Многие редко задумываются о такой важной части игры, и не удивительно, что могут вспомнить о ней в самый последний момент. Так что давайте поговорим немного о звуке.

Звук в Unity

Звуковые ассеты в Unity называются AudioClip, а их воспроизведение крутится вокруг двух компонентов AudioListener и AudioSource. AudioListener - это компонент, который ведёт себя как микрофон, он улавливает все звуки на сцене и проигрывает их через динамик. AudioSource - отвечает за проигрывание звука на сцене.

Соответственно, для того чтобы в игре был звук, необходимо добавить в какой-либо объект на сцене, компонент AudioListener, и обычно таким объектом становится камера. Нужно заметить, что нельзя добавлять больше одного листенера. А также необходимо добавить для всех воспроизводящих звук объектов компоненты AudioSource.

Можно разделить работу со звуком на три группы:

  • Фоновая музыка - её добавление мы рассмотрим в этой статьи
  • Звуки UI - приемлемым подходом будет добавление в необходимые UI элементы компонентов AudioSource, а их проигрывание привязать к UI эвентам этих элементов
  • Звуки в окружающем пространстве - эта группа несколько сложнее UI элементов, т.к. требует дополнительных механизмов накладывания звуков на динамические объекты, т.к. весь диапазон возможных звуков может быть довольно большим и их перечисление заранее довольно проблематичным. Работа с этой группой требует отдельного механизма и отдельной статьи =)

Задача

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

Реализация

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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KhtMusicManager : KhtSingleton<KhtMusicManager>
{
    // Задержка между треками
    public int newTrackDelay = 0;
    // Список треков
    public List<AudioClip> musicAudioClips = new List<AudioClip>();

    // Источник для проигрывания музыки
    private AudioSource _musicAudioSource = null;

    // Используется для отслеживания заглушения музыки
    private int _muted = 0;

    protected override void Awake()
    {
        // Настраиваем синглетон
        base.Awake();
        DontDestroyOnLoad(gameObject);

        // Добавляем компонент для проигрывания музыки
        _musicAudioSource = gameObject.AddComponent<AudioSource>();
    }
    
    // Start is called before the first frame update
    void Start()
    {
        // Запускаем проигрывание музыки
        StartCoroutine(PlayBackgroudMusic());
    }

    // Заглушаем музыку
    public static void Mute()
    {
        // Проверки для синглетона
        if (ReferenceEquals(Instance, null))
        {
            return;
        }

        // Если звук не заглушён
        if (Instance._muted == 0)
        {
            Instance._musicAudioSource.mute = true;
        }
        Instance._muted++;
    }

    // Возврат звука
    public static void TurnOn()
    {
        // Проверка на синглетон и запрет на отрицательный счётчик
        if (ReferenceEquals(Instance, null) || Instance._muted == 0)
        {
            return;
        }

        // Включаем звук
        Instance._muted--;
        if (Instance._muted == 0)
        {
            Instance._musicAudioSource.mute = false;
        }
        
    }

    // Запуск следующего трека
    IEnumerator PlayBackgroudMusic()
    {
        // Текущий индекс трека
        int musicIndex = 0;
        // Проигрываем музыку, если она есть
        while (musicAudioClips.Count > 0)
        {
            // Время для запуска следующего трека + задержка
            float waitTime = musicAudioClips[musicIndex].length + newTrackDelay;
            // Проигрываем мелодию один раз
            _musicAudioSource.PlayOneShot(musicAudioClips[musicIndex]);

            // Работа с текущим индексом трека
            musicIndex++;
            if (musicIndex >= musicAudioClips.Count)
            {
                musicIndex = 0;
            }

            // Задержка для включения следующего трека
            yield return new WaitForSeconds(waitTime);
        }
    }
}

Заключение

Приведённая реализация демонстрирует довольно низкий порог входа в работу со звуком в Unity. На базовом уровне система довольно проста, однако, при необходимости, можно использовать более продвинутые компоненты по смешиванию звуков и наложению эффектов(например, изменение звука двигателя при въезде в тоннель), также распространено использование сторонних библиотек. Возвращаясь к нашей реализации, можно выделить функционал, который хотелось бы добавить: возможность запуска трека по id, остановку и перезапуск, рандомизацию и хоть каждый такой запрос не является чем-то сложным, всё вместе это выходит за рамки статьи для начального ознакомления, так что оставим это на будущее. Пока! =)



Privacy policyCookie policyTerms of service
Tulenber 2020