Всем привет! Меня зовут Илья, я из команды TinyPlay. В этой статье хотел бы поделиться тем, как мы работаем с аудио. Надеюсь, для вас эта статья будет полезной.
Архитектура аудио
Проект состоит из 3-х составляющих: звуки (шаги, атмосфера, противники, оружие и многое многое другое), музыка (атмосферная, экшн-музыка, дополнительное сопровождение) и озвучка (персонажи, аудио-дневники, громокоговорители). Архитектура аудио разделена следующим образом:
Звуки:
Окружающая среда и все что с ней связано (листва, ветер, скрипы деревьев, ворот и пр.);
Звуки противников (атака, получение урона, обнаружение, смерть);
Звуки шагов для каждой из поверхностей (в общей сложности более 200 звуков под разные физические материалы);
Хоррор-звуки (вызываемые по триггерам);
Оружие (стрельба, перезарядка и пр.);
Звуки коллизий для физических объектов;
Звуки эффектов (взрывы, попадания, искры и пр.);
Другие звуки;
Музыка:
Атмосферная фоновая музыка;
Экшн музыка для определенных сцен;
Напряженная музыка;
Музыка в меню;
Озвучка:
Озвучка героев на разных языках;
Озвучка аудио-дневников;
Озвучка коммутаторов и другая озвучка;
Настройка компрессии для музыки и звуков различная. Музыка - стримится, большие звуки грузятся и распаковываются перед загрузкой сцены, мелкие звуки - налету.
Работа с музыкой и звуками. Микширование
Для достижения плавных переходов, различных звуковых областей и работе с компрессией - мы используем стандартный микшер Unity. Для плавных переходов - DOTween.
Пример того, как плавно переходит музыка в игре:
isSwitchingMusic = true;
MasterMixer.DOSetFloat("MainMusic", -80f, 2f);
MasterMixer.DOSetFloat("SecondMusic", 0f, 2f);
Микшеры также переключаются через особые Volume-зоны, которые меняют активный микшер или его настройки под окружающую среду (к примеру, чтобы в подвале был эффект эхо).
Пример работы с обнаружением материала террэйна:
namespace TinyPlay.Components
{
using UnityEngine;
public class TerrainDetector
{
private TerrainData terrainData;
private int alphamapWidth;
private int alphamapHeight;
private float[,,] splatmapData;
private int numTextures;
public TerrainDetector()
{
terrainData = Terrain.activeTerrain.terrainData;
alphamapWidth = terrainData.alphamapWidth;
alphamapHeight = terrainData.alphamapHeight;
splatmapData = terrainData.GetAlphamaps(0, 0, alphamapWidth, alphamapHeight);
numTextures = splatmapData.Length / (alphamapWidth * alphamapHeight);
}
private Vector3 ConvertToSplatMapCoordinate(Vector3 worldPosition)
{
Vector3 splatPosition = new Vector3();
Terrain ter = Terrain.activeTerrain;
Vector3 terPosition = ter.transform.position;
splatPosition.x = ((worldPosition.x - terPosition.x) / ter.terrainData.size.x) * ter.terrainData.alphamapWidth;
splatPosition.z = ((worldPosition.z - terPosition.z) / ter.terrainData.size.z) * ter.terrainData.alphamapHeight;
return splatPosition;
}
public int GetActiveTerrainTextureIdx(Vector3 position)
{
Vector3 terrainCord = ConvertToSplatMapCoordinate(position);
int activeTerrainIndex = 0;
float largestOpacity = 0f;
for (int i = 0; i < numTextures; i++)
{
if (largestOpacity < splatmapData[(int)terrainCord.z, (int)terrainCord.x, i])
{
activeTerrainIndex = i;
largestOpacity = splatmapData[(int)terrainCord.z, (int)terrainCord.x, i];
}
}
return activeTerrainIndex;
}
}
}
У нас используется плеер на основе эвентов анимаций, но вы сделать по-другому. Выше описан класс для определения материала террайна. Используя его - можно сопоставить поверхность со звуками.
Объемный звук. Рейтрейсинг и обнаружение геометрии
Мы перебрали несколько вариантов работы с объемным и главное физически-обоснованым звуком. Мы попробовали Steam Audio, FMOD, Microsoft Acoustics и др.
В итоге наш выбор пал на FMOD + Dolby Atmos + Microsoft Acousitcs. Почему не Steam Audio? Ну, мы получали непредвиденные вылеты в билдах на Windows со стороны их библиотеки, которые не могли отладить.
Для чего мы все это используем?
Для автоматического просчета распространения звука в окружающей среде, с учетом её геометрии, материалов и отражаемой способности (каждый объект в игре настраивается отдельно);
Для пространственной обработки аудио при помощи HRTF. В связке с Dolby Atmos звук получается максимально естественным.
Как это работает?
Система учитывает пространственное положение звука, источник его приема, угол и десятки других параметров для корректного восприятия, как в наушниках, так и на 5.1 системах.
Помимо этого, система при помощи рейтрейсинга (трассировки лучей в реальном времени) пробрасывает лучи для определения коллизий и отражений, применимых к звуковым волнам. Для снижения нагрузки эти расчеты производятся на GPU + звук запекается (аналогично Light Probes, но для звука).
Облачные вычисления для запекания звука
Запекать звук на сцене с тысячами 3D моделей и миллионами полигонов достаточно долго, поэтому мы используем облачные вычисления от Azure. Благо у Microsoft есть отличный инструмент на виртуальных машинах, предназначенный для этого - Azure Batch
Используя сервис облачных вычислений удается снизить время запекания звука с 2 часов до 10 минут, что существенно экономит время при достаточно низкой цене (1,5 бакса в час). При этом есть бесплатная подписка на Azure на 12,500Р, что подходит начинающим разработчикам.
Итого
Сочетание данных технологий позволяет нам добиваться более-менее реалистичного звука, а он, в свою очередь может сильно повлиять на атмосферу игры.
Полезные ссылки:
https://valvesoftware.github.io/steam-audio/