Как я могу воспроизвести аудиоклип при перемещении ползунка?

#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();