Перейти к содержимому

Как добавить звуки шагов в юнити

  • автор:

Звуки в Unity, Terrain

Начал разбираться со звуком в unity, посмотрел штук 30 видеороликов и везде все сводится к одному. «Сейчас мы покажем как сделать разные звуки шагов по разным поверхностям»
Берем то-то, то-то получаем TAG объекта.
В общем дальше можно не смотреть. К этому сводятся все уроки.
Ежу понятно, что можно менять звук при изменении TAG под объектом.

Существует ли какая-то более адекватная система определения поверхности аля звуковая карта поверхности?
Если у объекта нет TAG (untagged)? Или, предположим все объекты на сцене Untagged, или другой вариант, TAG используется для других целей и разные объекты с разными поверхностями могут иметь одинаковый TAG?

На объектах есть текстуры, я так понимаю можно определить какая преобладает под персонажем, это выглядит как-то более правильно. Может как-то можно определить это?

Какие вообще существуют методы для определения типа поверхности кроме получения tag объекта?
Тот же terrain имеет один tag, а типов поверхностей могут быть сотни.

Так из простых идей думаю под поверхность засунуть квадрат, раскрашенный разными цветами и определять цвет в точке и от этого определять звук поверхности (это чисто теоретически, так как не знаю можно ли определить цвет в точке), но это какая-то фигня с виду, наверняка есть как-то простой способ реализации, не знаю границы там какие-нибудь расставить?

Может скинете что-нибудь почитать/посмотреть?

Цель:
Cделать проверку поверхности без использования TAG объекта под персонажем.
(
— Коллайдеров нет кроме Terrain
— физики нет
— риджитбоди нет
— стандартный character controller не используется
— навмеш нет
— стандартные триггеры не работают
)

#1
14:40, 23 мая 2021

Для террейна можно брать тип поверхности из текстур, по которым слои смешиваются. Вот скрипт, который я использую в своём проекте (я его скопипастил откуда-то ещё, но сейчас что-то не получается найти откуда):

public enum SurfaceType < Stone, Rubble, Grass, Mud, Sand, Wood, Metal >public interface ISurfaceTypeDetector < public DictionaryGetSurfaceType(Vector3 point); > public class TerrainGroundTypeDetector : MonoBehaviour,ISurfaceTypeDetector < [SerializeField] private SurfaceType[] _surfaceTypes; private Terrain _terrain; private int _alphamapWidth; private int _alphamapHeight; private float[,,] _splatmapData; private int _texturesCount; private Dictionary_result = new Dictionary(); void Start() < GetTerrainProps(); >private void GetTerrainProps() < _terrain = GetComponent(); _alphamapWidth = _terrain.terrainData.alphamapWidth; _alphamapHeight = _terrain.terrainData.alphamapHeight; _splatmapData = _terrain.terrainData.GetAlphamaps(0, 0, _alphamapWidth, _alphamapHeight); _texturesCount = _splatmapData.Length / (_alphamapWidth * _alphamapHeight); > private Vector3 ConvertToSplatMapCoordinate(Vector3 worldPosition) < Vector3 vecRet = new Vector3(); Vector3 terPosition = _terrain.transform.position; vecRet.x = ((worldPosition.x - terPosition.x) / _terrain.terrainData.size.x) * _terrain.terrainData.alphamapWidth; vecRet.z = ((worldPosition.z - terPosition.z) / _terrain.terrainData.size.z) * _terrain.terrainData.alphamapHeight; return vecRet; >private int GetActiveTerrainTextureIdx(Vector3 worldPosition) < Vector3 TerrainCord = ConvertToSplatMapCoordinate(worldPosition); int ret = 0; float comp = 0f; for (int i = 0; i < _texturesCount; i++) < if (comp < _splatmapData[(int)TerrainCord.z, (int)TerrainCord.x, i]) ret = i; >return ret; > public Dictionary GetSurfaceType(Vector3 point) < _result.Clear(); Vector3 TerrainCord = ConvertToSplatMapCoordinate(point); for (int i = 0; i < _texturesCount; i++) < if (i < _surfaceTypes.Length) < float value = _splatmapData[(int)TerrainCord.z, (int)TerrainCord.x, i]; if (value >0) < if (_result.ContainsKey(_surfaceTypes[i])) < _result[_surfaceTypes[i]] = Mathf.Clamp01(value + _result[_surfaceTypes[i]]); >else < _result.Add(_surfaceTypes[i],value); >> > > return _result; > >

Скрипт возвращает не один тип, а словарь с несколькими типами, так как в одной точке террейна может смешиваться несколько текстур.
Массив _surfaceTypes задаётся в инспекторе в соответствии с тем, в каком порядке расположены текстурки в данном конкретном террейне.
Через интерфейс ISurfaceTypeDetector можно реализовать получение типа поверхности и для прочих объектов, помимо террейна.

Добавление звуков ходьбы в Unity

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

Мы не будем рассматривать реализацию самой ходьбы, а рассмотрим только воспроизведение звука ходьбы, в момент ходьбы. Но если по какой-либо причине Вы ещё не создали в своей игре движение игрока, то сначала предлагаем изучить гайд по реализации движения персонажа.

А теперь перейдём непосредственно к теме данной статьи. Для начала нам необходимо скачать звук ходьбы в интернете, и перетащить этот аудиофайл в окно Project. Так же можете переименовать данный файл на своё усмотрение. У меня он переименован в run.

Теперь для нашего персонажа создадим компонент Audio Source, который нужен для хранения и воспроизведения нашего аудиофайла шагов. После создания данного компонента, обратим своё внимание на три важных поля:

В поле AudioClip перетащите свой аудиофайл шагов из окна Project. В поле Play On Awake необходимо убрать галочку, чтобы наши шаги не воспроизводились сразу же, после запуска игры. Мы их сами будем воспроизводить в скрипте. А в поле Loop необходимо галочку всё же поставить, чтобы по завершению звукового файла, он воспроизводился снова и снова.

Остался последний штрих. Нам необходимо с помощью кода воспроизводить звук шагов, которые подгружены в компонент Audio Source в тот момент, когда персонаж идёт, и останавливать этот звук, когда персонаж не идёт. Для этого создадим новый скрипт C# с названием SoundRun, в котором пропишем следующее:

using UnityEngine; public class SoundRun : MonoBehaviour < public AudioSource moveSound; void Update() < if (Mathf.Abs(Input.GetAxis("Horizontal")) >0.35f && Mathf.Abs(Input.GetAxis("Vertical")) > 0.35f) < if (moveSound.isPlaying) return; moveSound.Play(); >else < moveSound.Stop(); >> >

В первой строке мы объявили переменную moveSound, в которой будет храниться ссылка на компонент AudioSource. Поэтому не забудьте в окне Inspector перетащить компонент Audio Source в поле moveSound.

В строке #9 мы проверяем, нажата ли кнопка движения игрока в одну из сторон: вправо, влево, вверх, вниз. И если да, то с помоью метода Play() воспроизводим наш аудиофайл шагов. А если кнопка движения не нажата, то принудительно останавливаем звук шагов с помощью метода Stop().

Так же обратите внимание, что в строке #11 у нас есть ещё одна проверка на то, воспроизводится ли звук шагов в данный момент? Если да, то ничего не делаем, поскольку так и надо. А если нет, то начинаем воспроизведение звука.

Важно: Чтобы не создавать множество скриптов, Вы можете скрипт SoundRun не создавать, а скопировать данный код в ваш скрипт, который отвечает за передвижение персонажа. Так будет более правильно.

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

На этом всё. Если остались вопросы, пишите в комментариях. А так же не забываем ставить алйки 🙂

Звуки в юнити 2D

Проблема такова. у меня есть код для воспроизведения звука при нажатии A, D, W. |A — ходьба влево| |D — ходьба вправо| |W — прыжок| не обращайте внимания на названия. мне так удобно.

public class aydio : MonoBehaviour < public AudioClip kek1; public AudioClip kek2; private AudioSource audio; void Start() < audio = GetComponent(); > void Update() < if (Input.GetKeyDown(KeyCode.W)) audio.PlayOneShot(kek1); if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)) audio.PlayOneShot(kek2); >> 

Проблема в том что звуки ходьбы накладываются друг на друга, и я не знаю как чередовать например 4 звука шага в разном порядке. Как сделать случайное чередование звуков ходьбы, чтобы они не накладывались друг на друга и не останавливались пока не кнопку не отпустят. плиз, пишите простым языком.

Отслеживать
677 3 3 серебряных знака 20 20 бронзовых знаков
задан 10 дек 2020 в 18:00
Dark Lord Tehnology Dark Lord Tehnology
35 6 6 бронзовых знаков

было бы еще круто если еще сказали бы, как сделать настройку этого звука из игры . и чтобы это сохранялось

11 дек 2020 в 14:28

не обращайте внимания на названия. мне так удобноkek1, kek2пишите простым языком — Ну-ну. То есть вы будете писать абы как, а вам должны писать понятно.

17 дек 2020 в 2:09

с чего вы взяли что я пишу абы как ? «пишите простым языком» я имел виду без сложных понятий, а на простом языке .

Как сделать звуки шагов? [FPS]

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

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

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

Создаем класс, который отвечает за загрузку и воспроизведение:

using UnityEngine; using System.Collections; [RequireComponent(typeof(AudioSource))] public class Footsteps : MonoBehaviour < public enum StepsOn ; // mainFolder - родительская папка в Resources // betonFolder и т.д. дочерние private string mainFolder = "Footsteps", betonFolder = "Beton", woodFolder = "Wood", metalFolder = "Metal", groundFolder = "Ground"; private AudioClip[] Beton, Wood, Metal, Ground; private AudioSource source; private AudioClip clip; void Start() < source = GetComponent(); source.playOnAwake = false; source.mute = false; source.loop = false; LoadSounds(); > void LoadSounds() < Beton = Resources.LoadAll(mainFolder + "/" + betonFolder); Wood = Resources.LoadAll(mainFolder + "/" + woodFolder); Metal = Resources.LoadAll(mainFolder + "/" + metalFolder); Ground = Resources.LoadAll(mainFolder + "/" + groundFolder); > public void PlayStep(StepsOn stepsOn, float volume) < switch(stepsOn) < case StepsOn.Beton: clip = Beton[Random.Range(0, Beton.Length)]; break; case StepsOn.Wood: clip = Wood[Random.Range(0, Wood.Length)]; break; case StepsOn.Metal: clip = Metal[Random.Range(0, Metal.Length)]; break; case StepsOn.Ground: clip = Ground[Random.Range(0, Ground.Length)]; break; >source.PlayOneShot(clip, volume); > >

Здесь есть меню, для выбора определенных звуков. Меню можно конечно расширить, если это нужно.

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

using UnityEngine; using System.Collections; [RequireComponent(typeof(Rigidbody))] [RequireComponent(typeof(Footsteps))] public class PlayerControl : MonoBehaviour < [Header("General")] public float speed = 1.5f; // скорость движения public float acceleration = 100f; // ускорение public float stepTimer = 0.8f; // интервал шагов во время ходьбы (секунды) [Header("Head / Camera")] public Transform head; public float sensitivity = 5f; // чувствительность мыши public float headMinY = -40f; // ограничение угла для головы public float headMaxY = 40f; [Header("Jump")] public KeyCode jumpButton = KeyCode.Space; // клавиша для прыжка public float jumpForce = 10; // сила прыжка public float jumpDistance = 1.2f; // расстояние от центра объекта, до поверхности [Header("Run")] public KeyCode runButton = KeyCode.LeftShift; // клавиша для бега public float addForce = 5; // добавить к скорости public float stepTimerRun = 0.35f; // интервал шагов во время бега (секунды) private Vector3 direction; private int layerMask; private Rigidbody body; private float rotY, curT, h, v, curSpeed, curStepTimer; private string tagName; private bool fall; private Footsteps foot; void Start () < foot = GetComponent(); body = GetComponent(); body.freezeRotation = true; layerMask = 1 void FixedUpdate() < body.AddForce(direction.normalized * curSpeed * acceleration * body.mass); // Ограничение скорости, иначе объект будет постоянно ускоряться if(Mathf.Abs(body.velocity.x) >curSpeed) < body.velocity = new Vector3(Mathf.Sign(body.velocity.x) * curSpeed, body.velocity.y, body.velocity.z); >if(Mathf.Abs(body.velocity.z) > curSpeed) < body.velocity = new Vector3(body.velocity.x, body.velocity.y, Mathf.Sign(body.velocity.z) * curSpeed); >> bool GetJump() // проверяем, есть ли коллайдер под ногами < RaycastHit hit; Ray ray = new Ray(transform.position, Vector3.down); if(Physics.Raycast(ray, out hit, jumpDistance, layerMask)) < tagName = hit.transform.tag; // берем тег поверхности return true; >tagName = string.Empty; return false; > void Update () < curSpeed = speed; curStepTimer = stepTimer; h = Input.GetAxis("Horizontal"); v = Input.GetAxis("Vertical"); // управление головой (камерой) float rotX = head.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivity; rotY += Input.GetAxis("Mouse Y") * sensitivity; rotY = Mathf.Clamp (rotY, headMinY, headMaxY); head.localEulerAngles = new Vector3(-rotY, rotX, 0); // вектор направления движения direction = new Vector3(h, 0, v); direction = head.TransformDirection(direction); direction = new Vector3(direction.x, 0, direction.z); Debug.DrawRay(transform.position, Vector3.down * jumpDistance, Color.red); // подсветка, для визуальной настройки jumpDistance if(Input.GetKey(runButton)) // если удерживать клавишу бега < curSpeed = speed + addForce; curStepTimer = stepTimerRun; >if(GetJump()) < if(Input.GetKeyDown(jumpButton)) < body.velocity = new Vector2(0, jumpForce); >Steps(); Falling(); > else < curT = 0; fall = true; >> void Falling() // падение на что-нибудь < if(fall) < fall = false; curT = 0; GetStep(); >> void Steps() < // округляем текущее значение скорости по оси X и Z, до сотых // чтобы исключить те, которые близкие к нулю, например: 0.000001805331f // в противном случаи, функция будет срабатывать, даже если персонаж не движется float velocityZ = RoundTo(Mathf.Abs(body.velocity.z), 100); float velocityX = RoundTo(Mathf.Abs(body.velocity.x), 100); if(velocityZ >0 && Mathf.Abs(v) > 0 || velocityX > 0 && Mathf.Abs(h) > 0) // если персонаж движется < curT += Time.deltaTime; if(curT >curStepTimer) < curT = 0; GetStep(); >> else < curT = 1000; >> void GetStep() // фильтр по тегу < switch(tagName) < case "GameController": foot.PlayStep(Footsteps.StepsOn.Beton, 1); break; case "Finish": foot.PlayStep(Footsteps.StepsOn.Ground, 1); break; >> float RoundTo(float f, int to) // округлить до, указанного значения < return ((int)(f*to))/(float)to; >>

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *