AudioRandomContainer and its base class AudioResource were introduced to the engine fairly recently and can be assigned to an AudioSource to play a random sound. However, if you want to use more than one random sound you need more than one AudioSource because the PlayOneShot method does not yet accept an AudioResource as a parameter
5 Likes
Another method that needs support for AudioResource is PlayClipAtPoint as well as any other AudioSource method that accepts an AudioClip
Bumping this. We don’t even have access to AudioRandomContainer’s API which means we can’t even create an temporary bridge.
2 Likes
I’ve rolled my own PlayOneShot that supports an AudioResource. It’s basically an object pool of AudioSources. Hacky.
1 Like
Care to share?
Sure! This is for my Match 3 game, so I don’t have any moving audio sources to worry about. It’s not much cuz non-game mechanic systems are low on my to-do list atm.
(Bonus, it doesn’t play the same sound multiple times if PlaySFX() is called multiple times in the same frame)
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
namespace _main
{
public class GameAudioManager : MonoBehaviour
{
public static GameAudioManager Instance { get; private set; }
[SerializeField] private float _timeBetweenSFX;
[Header("Mixer Groups")]
[SerializeField] private AudioMixerGroup _sfxAudioMixerGroup;
[SerializeField] private AudioMixerGroup _musicAudioMixerGroup;
private List<AudioSource> _gameSFXAudioSources = new();
private Dictionary<AudioResource, float> _lastPlayed = new();
private AudioSource _source;
private void Awake()
{
if(Instance == null)
{
Instance = this;
Services.Audio.Game = this;
}
else
{
Destroy(this);
}
}
private void OnEnable()
{
for(int x = 0; x < 16; x++)
{
_gameSFXAudioSources.Add(gameObject.AddComponent<AudioSource>());
_gameSFXAudioSources[^1].outputAudioMixerGroup = _sfxAudioMixerGroup;
}
}
public void PlaySFX(AudioResource audioResource)
{
if(_lastPlayed.ContainsKey(audioResource))
{
if(Time.time - _lastPlayed[audioResource] < _timeBetweenSFX)
{
return;
}
}
else
{
_lastPlayed.Add(audioResource, Time.time);
}
_lastPlayed[audioResource] = Time.time;
_source = GetFreeGameSFXAudioSource();
_source.resource = audioResource;
_source.Play();
}
private AudioSource GetFreeGameSFXAudioSource()
{
foreach(AudioSource a in _gameSFXAudioSources)
{
if(!a.isPlaying)
{
return a;
}
}
GameLog.Instance.Log($"{Time.time} Creating new AudioSource", GameLog.Type.Warning);
_gameSFXAudioSources.Add(gameObject.AddComponent<AudioSource>());
return _gameSFXAudioSources[^1];
}
}
}
1 Like