#c# #unity3d #audio
#c# #unity3d #Аудио
Вопрос:
Как и в моем другом вопросе, я использую один аудиомикшер с двумя группами для игровой сцены и сцены главного меню.
В сцене главного меню у меня есть источник звука для музыки и источник звука для эффектов sfx. При запуске игры в главном меню музыка воспроизводится автоматически при пробуждении.,
Sfx не воспроизводится, и я хочу, чтобы при изменении ползунка sfx на короткое время звучал эффект sfx, поэтому каждый раз, когда я меняю значение ползунка, он будет воспроизводить sfx, чтобы услышать его громкость.
Ползунки, как они выглядят в игре :
Сценарий настроек, когда я устанавливаю также громкость звука :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;
using TMPro;
using System;
using UnityEngine.Events;
using System.Linq;
public class Settings : MonoBehaviour
{
public AudioMixer audioMixer;
public TMP_Dropdown resolutionDropdown;
public TMP_Dropdown qualityDropdown;
public Text musicText;
public Text sfxText;
public Slider[] audioSliders;
public Toggle fullScreenToggle;
private Resolution[] resolutions;
private void Awake()
{
resolutionDropdown.onValueChanged.AddListener(new UnityAction<int>(index =>
{
PlayerPrefs.SetInt("resolutionvalue", resolutionDropdown.value);
PlayerPrefs.Save();
}));
qualityDropdown.onValueChanged.AddListener(new UnityAction<int>(index =>
{
PlayerPrefs.SetInt("qualityvalue", qualityDropdown.value);
PlayerPrefs.Save();
}));
fullScreenToggle.onValueChanged.AddListener(new UnityAction<bool>(index =>
{
PlayerPrefs.SetInt("fullscreen", boolToInt(fullScreenToggle.isOn));
PlayerPrefs.Save();
}));
}
private void Start()
{
qualityDropdown.value = PlayerPrefs.GetInt("qualityvalue");
var resolutions = Screen.resolutions.Where(resolution => resolution.refreshRate == 60).ToArray();
resolutionDropdown.ClearOptions();
List<string> options = new List<string>();
int currentResolutionIndex = 0;
for(int i = 0; i < resolutions.Length; i )
{
string option = resolutions[i].width " x " resolutions[i].height;
options.Add(option);
if(resolutions[i].width == Screen.currentResolution.width amp;amp;
resolutions[i].height == Screen.currentResolution.height)
{
currentResolutionIndex = i;
}
}
resolutionDropdown.AddOptions(options);
resolutionDropdown.value = PlayerPrefs.GetInt("resolutionvalue", currentResolutionIndex);
resolutionDropdown.RefreshShownValue();
float musicvolume = PlayerPrefs.GetFloat("musicvolume");
float sfxvolume = PlayerPrefs.GetFloat("sfxvolume");
musicText.text = musicvolume.ToString();
sfxText.text = sfxvolume.ToString();
audioSliders[0].value = musicvolume / 100f;
audioSliders[1].value = sfxvolume / 100f;
fullScreenToggle.isOn = intToBool(PlayerPrefs.GetInt("fullscreen", 0));
}
public void SetResolution(int resolutionIndex)
{
if (resolutions != null)
{
Resolution resolution = resolutions[resolutionIndex];
Screen.SetResolution(resolution.width, resolution.height, Screen.fullScreen);
}
}
public void SetMusicVolume(float volume)
{
audioMixer.SetFloat("musicvol", Mathf.Log10(volume) * 20);
musicText.text = Math.Round(volume * 100, MidpointRounding.AwayFromZero).ToString();
PlayerPrefs.SetFloat("musicvolume", (float)Math.Round(volume * 100, MidpointRounding.AwayFromZero));
}
public void SetSfxVolume(float volume)
{
audioMixer.SetFloat("sfxvol", Mathf.Log10(volume) * 20);
sfxText.text = Math.Round(volume * 100, MidpointRounding.AwayFromZero).ToString();
PlayerPrefs.SetFloat("sfxvolume", (float)Math.Round(volume * 100, MidpointRounding.AwayFromZero));
}
public void SetQuality(int qualityIndex)
{
QualitySettings.SetQualityLevel(qualityIndex);
}
public void SetFullscreen(bool isFullscreen)
{
Screen.fullScreen = isFullscreen;
}
int boolToInt(bool val)
{
if (val)
return 1;
else
return 0;
}
bool intToBool(int val)
{
if (val != 0)
return true;
else
return false;
}
}
Возможно, вся моя логика неверна, но я хочу дать проигрывателю возможность изменять громкость музыки и sfx, чтобы решить, что будет загружаться, а что меньше.
Ответ №1:
Вы могли бы сделать это, например
[SerializeField] private AudioSource SfxSource;
public void SetSfxVolume(float volume)
{
audioMixer.SetFloat("sfxvol", Mathf.Log10(volume) * 20);
sfxText.text = Math.Round(volume * 100, MidpointRounding.AwayFromZero).ToString();
PlayerPrefs.SetFloat("sfxvolume", (float)Math.Round(volume * 100, MidpointRounding.AwayFromZero));
if(!SfxSource.isPlaying) SfxSource.Play();
}
Или использовать AudioSource.PlayOneShot
.
Комментарии:
1. Я использовал точку останова в этой строке: if (!SfxSource.isPlaying), и это всегда верно при перемещении ползунка громкости sfx. Это никогда не бывает ложным.
2. Мне удалось заставить его работать. Поскольку два источника звука находятся в одном и том же gameobject, я немного изменил сценарий. Вверху вместо одного аудиоисточника я сделал массив: [SerializeField] частный аудиоисточник[] аудиоисточники; затем в функции sfx: if (!Аудиоисточники[1].isPlaying) аудиоисточники[1].Play();
3. Теперь я столкнулся с другой проблемой. Если я перемещаю ползунок слишком быстро, он снова начнет воспроизводить sfx, когда я остановлю ползунок. Итак, если я нахожусь в значении 7 и быстро переместил ползунок на 23, он снова воспроизведет его при значении 23. но я хочу, чтобы он воспроизводился при каждом значении ползунка при медленном или быстром перемещении ползунка. Есть идеи, как это решить?
4. в этом случае вы можете пропустить проверку и просто использовать
SfxSource.Play();