Files
2025-06-09 23:23:13 +08:00

159 lines
5.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace JBooth.MicroVerseCore
{
internal class AmbientState
{
static Stack<AudioSource> audioSourcePool = new Stack<AudioSource>();
static List<AudioSource> releaseSourceList = new List<AudioSource>();
List<RandomSoundState> soundStates = new List<RandomSoundState>();
internal Ambient ambient;
internal static AudioSource GetAudioSource()
{
if (audioSourcePool.Count == 0)
{
GameObject go = new GameObject("Ambient Sound");
go.hideFlags = HideFlags.HideAndDontSave;
var s = go.AddComponent<AudioSource>();
s.loop = false;
s.hideFlags = HideFlags.DontSave;
s.playOnAwake = false;
releaseSourceList.Add(s);
return s;
}
else
{
var s = audioSourcePool.Pop();
releaseSourceList.Add(s);
return s;
}
}
internal class RandomSoundState
{
internal Ambient.RandomSound rs;
float timeUntilTrigger = 0;
void NextTrigger()
{
timeUntilTrigger = UnityEngine.Random.Range(rs.delay - rs.delayVariance, rs.delay + rs.delayVariance);
if (timeUntilTrigger < 0.05f)
timeUntilTrigger = Mathf.Max(rs.delay, 0.05f);
}
internal RandomSoundState(Ambient.RandomSound r)
{
rs = r;
NextTrigger();
}
internal void UpdateState(Ambient a, AmbientArea area, Vector3 listenerPos)
{
timeUntilTrigger -= Time.smoothDeltaTime * area.audioChance;
if (timeUntilTrigger < 0)
{
var s = GetAudioSource();
s.pitch = Random.Range(rs.pitch - rs.pitchVariance, rs.pitch + rs.pitchVariance);
s.volume = Random.Range(rs.volume - rs.volumeVariance, rs.volume + rs.volumeVariance) * AmbianceMgr.ambientLevel;
s.spatialBlend = rs.spacialization;
s.outputAudioMixerGroup = a.outputGroup;
s.spatialize = rs.spacialization > 0 ? true : false;
if (s.spatialize)
{
Vector3 soundPos;
if (area.falloff == AmbientArea.AmbianceFalloff.Range || rs.playerRadius > 0)
{
soundPos = Random.insideUnitSphere;
}
else
{
soundPos = new Vector3(Random.Range(-1.0f, 1.0f),
Random.Range(-1.0f, 1.0f),
Random.Range(-1.0f, 1.0f));
}
if (rs.playerRadius > 0)
{
soundPos = listenerPos + soundPos * rs.playerRadius;
}
else
{
soundPos = area.transform.localToWorldMatrix.MultiplyPoint(soundPos);
}
if (rs.minimumDistance > 0)
{
float dist = Vector3.Distance(soundPos, listenerPos);
if (dist < rs.minimumDistance)
{
soundPos = Vector3.Normalize(soundPos - listenerPos) * rs.minimumDistance;
}
}
s.transform.position = soundPos;
}
var clip = rs.clips[UnityEngine.Random.Range(0, rs.clips.Length)];
if (clip != null)
{
s.PlayOneShot(clip);
}
else
{
Debug.LogWarning("Null Clip found in Ambient " + a.name);
}
NextTrigger();
}
}
}
internal AmbientState(Ambient a)
{
ambient = a;
for (int i = 0; i < a.randomSounds.Length; ++i)
{
var rs = a.randomSounds[i];
if (rs.clips == null || rs.clips.Length == 0)
{
Debug.LogWarning("Ambient with no clips in Random Sound list");
}
else
{
RandomSoundState state = new RandomSoundState(rs);
soundStates.Add(state);
}
}
}
internal void UpdateState(AmbientArea area, Vector3 listenerPos)
{
for (int i = 0; i < releaseSourceList.Count; ++i)
{
if (!releaseSourceList[i].isPlaying)
{
var s = releaseSourceList[i];
releaseSourceList.RemoveAt(i);
i--;
audioSourcePool.Push(s);
}
}
for (int i = 0; i < soundStates.Count; ++i)
{
soundStates[i].UpdateState(ambient, area, listenerPos);
}
}
}
}